Print this page
4953763 Need way to configure NFS window sizes without changing system wide defaults
6216670 NFS server needs a bigger transmit buffer

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/fs.d/nfs/lib/nfs_tbind.c
          +++ new/usr/src/cmd/fs.d/nfs/lib/nfs_tbind.c
↓ open down ↓ 11 lines elided ↑ open up ↑
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22      - * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
       22 + * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   */
  25   25  
  26   26  /*
  27   27   * nfs_tbind.c, common part for nfsd and lockd.
  28   28   */
  29   29  
  30      -#pragma ident   "%Z%%M% %I%     %E% SMI"
  31      -
  32   30  #define PORTMAP
  33   31  
  34   32  #include <tiuser.h>
  35   33  #include <fcntl.h>
  36   34  #include <netconfig.h>
  37   35  #include <stropts.h>
  38   36  #include <errno.h>
  39   37  #include <syslog.h>
  40   38  #include <rpc/rpc.h>
  41   39  #include <rpc/pmap_prot.h>
↓ open down ↓ 54 lines elided ↑ open up ↑
  96   94  /*
  97   95   * this file contains transport routines common to nfsd and lockd
  98   96   */
  99   97  static  int     nofile_increase(int);
 100   98  static  int     reuseaddr(int);
 101   99  static  int     recvucred(int);
 102  100  static  int     anonmlp(int);
 103  101  static  void    add_to_poll_list(int, struct netconfig *);
 104  102  static  char    *serv_name_to_port_name(char *);
 105  103  static  int     bind_to_proto(char *, char *, struct netbuf **,
 106      -                                struct netconfig **);
      104 +                                struct netconfig **, int, int);
 107  105  static  int     bind_to_provider(char *, char *, struct netbuf **,
 108      -                                        struct netconfig **);
      106 +                                struct netconfig **, int, int);
 109  107  static  void    conn_close_oldest(void);
 110  108  static  boolean_t conn_get(int, struct netconfig *, struct conn_ind **);
 111  109  static  void    cots_listen_event(int, int);
 112  110  static  int     discon_get(int, struct netconfig *, struct conn_ind **);
 113  111  static  int     do_poll_clts_action(int, int);
 114  112  static  int     do_poll_cots_action(int, int);
 115  113  static  void    remove_from_poll_list(int);
 116  114  static  int     set_addrmask(int, struct netconfig *, struct netbuf *);
 117  115  static  int     is_listen_fd_index(int);
 118  116  
 119  117  static  struct pollfd *poll_array;
 120  118  static  struct conn_entry *conn_polled;
 121  119  static  int     num_conns;              /* Current number of connections */
 122  120  int             (*Mysvc4)(int, struct netbuf *, struct netconfig *, int,
 123  121                  struct netbuf *);
      122 +static int      setopt(int fd, int level, int name, int value);
 124  123  
 125  124  extern bool_t __pmap_set(const rpcprog_t program, const rpcvers_t version,
 126  125      const struct netconfig *nconf, const struct netbuf *address);
 127  126  
 128  127  /*
 129  128   * Called to create and prepare a transport descriptor for in-kernel
 130  129   * RPC service.
 131  130   * Returns -1 on failure and a valid descriptor on success.
 132  131   */
 133  132  int
↓ open down ↓ 99 lines elided ↑ open up ↑
 233  232  
 234  233          if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
 235  234                  syslog(LOG_ERR, "setrlimit of NOFILE to %d failed: %m",
 236  235                      rl.rlim_cur);
 237  236                  return (-1);
 238  237          }
 239  238  
 240  239          return (0);
 241  240  }
 242  241  
      242 +static int
      243 +nfslib_set_sockbuf(int fd, int which, int val)
      244 +{
      245 +        if ((which != SO_RCVBUF) && (which != SO_SNDBUF))
      246 +                return (-1);
      247 +
      248 +        syslog(LOG_DEBUG, "Set %s option to %d",
      249 +            ((which == SO_RCVBUF) ? "SO_RCVBUF" : "SO_SNDBUF"), val);
      250 +
      251 +        if (setopt(fd, SOL_SOCKET, which, val) < 0) {
      252 +                syslog(LOG_ERR, "couldn't set %s to %d - t_errno = %d",
      253 +                    ((which == SO_RCVBUF) ? "SO_RCVBUF" : "SO_SNDBUF"),
      254 +                    val, t_errno);
      255 +                syslog(LOG_ERR, "Check and increase system-wide tcp_max_buf");
      256 +                return (-1);
      257 +        }
      258 +        return (0);
      259 +}
      260 +
 243  261  int
 244  262  nfslib_bindit(struct netconfig *nconf, struct netbuf **addr,
 245      -        struct nd_hostserv *hs, int backlog)
      263 +        struct nd_hostserv *hs, int backlog, int sndbufsz, int rcvbufsz)
 246  264  {
 247  265          int fd;
 248  266          struct t_bind  *ntb;
 249  267          struct t_bind tb;
 250  268          struct nd_addrlist *addrlist;
 251  269          struct t_optmgmt req, resp;
 252  270          struct opthdr *opt;
 253  271          char reqbuf[128];
 254  272          bool_t use_any = FALSE;
 255  273          bool_t gzone = TRUE;
↓ open down ↓ 139 lines elided ↑ open up ↑
 395  413                  resp.flags = 0;
 396  414                  resp.opt.buf = reqbuf;
 397  415                  resp.opt.maxlen = sizeof (reqbuf);
 398  416  
 399  417                  if (t_optmgmt(fd, &req, &resp) < 0 ||
 400  418                      resp.flags != T_SUCCESS) {
 401  419                          syslog(LOG_ERR,
 402  420          "couldn't set NODELAY option for proto %s: t_errno = %d, %m",
 403  421                              nconf->nc_proto, t_errno);
 404  422                  }
      423 +
      424 +                if (sndbufsz > 0)
      425 +                        (void) nfslib_set_sockbuf(fd, SO_SNDBUF, sndbufsz);
      426 +                if (rcvbufsz > 0)
      427 +                        (void) nfslib_set_sockbuf(fd, SO_RCVBUF, rcvbufsz);
 405  428          }
 406  429  
 407  430          return (fd);
 408  431  }
 409  432  
 410  433  static int
 411  434  setopt(int fd, int level, int name, int value)
 412  435  {
 413  436          struct t_optmgmt req, resp;
 414  437          struct {
↓ open down ↓ 55 lines elided ↑ open up ↑
 470  493                      tli_name, fd, nconf->nc_proto);
 471  494          } else {
 472  495                  syslog(LOG_ERR,
 473  496                      "%s(file descriptor %d/transport %s) TLI error %d",
 474  497                      tli_name, fd, nconf->nc_proto, t_errno);
 475  498          }
 476  499          errno = error;
 477  500  }
 478  501  
 479  502  /*
 480      - * Called to set up service over a particular transport.
      503 + * Called to set up service over a particular transport also
      504 + * set send and receive buffer size for transport connection.
 481  505   */
 482  506  void
 483      -do_one(char *provider, NETSELDECL(proto), struct protob *protobp0,
 484      -        int (*svc)(int, struct netbuf, struct netconfig *), int use_pmap)
      507 +do_one_setbuf(char *provider, NETSELDECL(proto), struct protob *protobp0,
      508 +        int (*svc)(int, struct netbuf, struct netconfig *), int use_pmap,
      509 +        int sndbufsz, int rcvbufsz)
 485  510  {
 486  511          register int sock;
 487  512          struct protob *protobp;
 488  513          struct netbuf *retaddr;
 489  514          struct netconfig *retnconf;
 490  515          struct netbuf addrmask;
 491  516          int vers;
 492  517          int err;
 493  518          int l;
 494  519  
 495  520          if (provider)
 496  521                  sock = bind_to_provider(provider, protobp0->serv, &retaddr,
 497      -                    &retnconf);
      522 +                    &retnconf, sndbufsz, rcvbufsz);
 498  523          else
 499  524                  sock = bind_to_proto(proto, protobp0->serv, &retaddr,
 500      -                    &retnconf);
      525 +                    &retnconf, sndbufsz, rcvbufsz);
 501  526  
 502  527          if (sock == -1) {
 503  528                  (void) syslog(LOG_ERR,
 504  529          "Cannot establish %s service over %s: transport setup problem.",
 505  530                      protobp0->serv, provider ? provider : proto);
 506  531                  return;
 507  532          }
 508  533  
 509  534          if (set_addrmask(sock, retnconf, &addrmask) < 0) {
 510  535                  (void) syslog(LOG_ERR,
↓ open down ↓ 64 lines elided ↑ open up ↑
 575  600                          exit(1);
 576  601                  }
 577  602          }
 578  603  
 579  604          /*
 580  605           * We successfully set up the server over this transport.
 581  606           * Add this descriptor to the one being polled on.
 582  607           */
 583  608          add_to_poll_list(sock, retnconf);
 584  609  }
      610 +
 585  611  /*
 586      - * Set up the NFS service over all the available transports.
      612 + * Set up the NFS service over all the available transports and
      613 + * also set send and receive buffer size for transport connection.
 587  614   * Returns -1 for failure, 0 for success.
 588  615   */
 589  616  int
 590      -do_all(struct protob *protobp,
 591      -        int (*svc)(int, struct netbuf, struct netconfig *), int use_pmap)
      617 +do_all_setbuf(struct protob *protobp,
      618 +        int (*svc)(int, struct netbuf, struct netconfig *), int use_pmap,
      619 +        int sndbufsz, int rcvbufsz)
 592  620  {
 593  621          struct netconfig *nconf;
 594  622          NCONF_HANDLE *nc;
 595  623          int l;
 596  624  
 597  625          if ((nc = setnetconfig()) == (NCONF_HANDLE *)NULL) {
 598  626                  syslog(LOG_ERR, "setnetconfig failed: %m");
 599  627                  return (-1);
 600  628          }
 601  629          l = strlen(NC_UDP);
 602  630          while (nconf = getnetconfig(nc)) {
 603  631                  if ((nconf->nc_flag & NC_VISIBLE) &&
 604  632                      strcmp(nconf->nc_protofmly, NC_LOOPBACK) != 0 &&
 605  633                      OK_TPI_TYPE(nconf) &&
 606  634                      (protobp->program != NFS4_CALLBACK ||
 607  635                      strncasecmp(nconf->nc_proto, NC_UDP, l) != 0))
 608      -                        do_one(nconf->nc_device, nconf->nc_proto,
 609      -                            protobp, svc, use_pmap);
      636 +                        do_one_setbuf(nconf->nc_device, nconf->nc_proto,
      637 +                            protobp, svc, use_pmap, sndbufsz, rcvbufsz);
 610  638          }
 611  639          (void) endnetconfig(nc);
 612  640          return (0);
 613  641  }
 614  642  
 615  643  /*
      644 + * Called to set up service over a particular transport.
      645 + */
      646 +void
      647 +do_one(char *provider, NETSELDECL(proto), struct protob *protobp0,
      648 +        int (*svc)(int, struct netbuf, struct netconfig *), int use_pmap)
      649 +{
      650 +        do_one_setbuf(provider, proto, protobp0, svc, use_pmap, 0, 0);
      651 +}
      652 +
      653 +/*
      654 + * Set up the NFS service over all the available transports.
      655 + * Returns -1 for failure, 0 for success.
      656 + */
      657 +int
      658 +do_all(struct protob *protobp,
      659 +        int (*svc)(int, struct netbuf, struct netconfig *), int use_pmap)
      660 +{
      661 +        return (do_all_setbuf(protobp, svc, use_pmap, 0, 0));
      662 +}
      663 +
      664 +/*
 616  665   * poll on the open transport descriptors for events and errors.
 617  666   */
 618  667  void
 619  668  poll_for_action(void)
 620  669  {
 621  670          int nfds;
 622  671          int i;
 623  672  
 624  673          /*
 625  674           * Keep polling until all transports have been closed. When this
↓ open down ↓ 944 lines elided ↑ open up ↑
1570 1619                  return ("lockd");
1571 1620          } else if (strcmp(name, "NFS4_CALLBACK") == 0) {
1572 1621                  return ("nfs4_callback");
1573 1622          }
1574 1623  
1575 1624          return ("unrecognized");
1576 1625  }
1577 1626  
1578 1627  static int
1579 1628  bind_to_provider(char *provider, char *serv, struct netbuf **addr,
1580      -                struct netconfig **retnconf)
     1629 +                struct netconfig **retnconf, int sndbufsz, int rcvbufsz)
1581 1630  {
1582 1631          struct netconfig *nconf;
1583 1632          NCONF_HANDLE *nc;
1584 1633          struct nd_hostserv hs;
1585 1634  
1586 1635          hs.h_host = HOST_SELF;
1587 1636          hs.h_serv = serv_name_to_port_name(serv);
1588 1637  
1589 1638          if ((nc = setnetconfig()) == (NCONF_HANDLE *)NULL) {
1590 1639                  syslog(LOG_ERR, "setnetconfig failed: %m");
1591 1640                  return (-1);
1592 1641          }
1593 1642          while (nconf = getnetconfig(nc)) {
1594 1643                  if (OK_TPI_TYPE(nconf) &&
1595 1644                      strcmp(nconf->nc_device, provider) == 0) {
1596 1645                          *retnconf = nconf;
1597 1646                          return (nfslib_bindit(nconf, addr, &hs,
1598      -                            listen_backlog));
     1647 +                            listen_backlog, sndbufsz, rcvbufsz));
1599 1648                  }
1600 1649          }
1601 1650          (void) endnetconfig(nc);
1602 1651  
1603 1652          syslog(LOG_ERR, "couldn't find netconfig entry for provider %s",
1604 1653              provider);
1605 1654          return (-1);
1606 1655  }
1607 1656  
1608 1657  static int
1609 1658  bind_to_proto(NETSELDECL(proto), char *serv, struct netbuf **addr,
1610      -                struct netconfig **retnconf)
     1659 +                struct netconfig **retnconf, int sndbufsz, int rcvbufsz)
1611 1660  {
1612 1661          struct netconfig *nconf;
1613 1662          NCONF_HANDLE *nc = NULL;
1614 1663          struct nd_hostserv hs;
1615 1664  
1616 1665          hs.h_host = HOST_SELF;
1617 1666          hs.h_serv = serv_name_to_port_name(serv);
1618 1667  
1619 1668          if ((nc = setnetconfig()) == (NCONF_HANDLE *)NULL) {
1620 1669                  syslog(LOG_ERR, "setnetconfig failed: %m");
1621 1670                  return (-1);
1622 1671          }
1623 1672          while (nconf = getnetconfig(nc)) {
1624 1673                  if (OK_TPI_TYPE(nconf) && NETSELEQ(nconf->nc_proto, proto)) {
1625 1674                          *retnconf = nconf;
1626 1675                          return (nfslib_bindit(nconf, addr, &hs,
1627      -                            listen_backlog));
     1676 +                            listen_backlog, sndbufsz, rcvbufsz));
1628 1677                  }
1629 1678          }
1630 1679          (void) endnetconfig(nc);
1631 1680  
1632 1681          syslog(LOG_ERR, "couldn't find netconfig entry for protocol %s",
1633 1682              proto);
1634 1683          return (-1);
1635 1684  }
1636 1685  
1637 1686  #include <netinet/in.h>
↓ open down ↓ 75 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX