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

*** 17,36 **** * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* ! * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * nfs_tbind.c, common part for nfsd and lockd. */ - #pragma ident "%Z%%M% %I% %E% SMI" - #define PORTMAP #include <tiuser.h> #include <fcntl.h> #include <netconfig.h> --- 17,34 ---- * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* ! * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * nfs_tbind.c, common part for nfsd and lockd. */ #define PORTMAP #include <tiuser.h> #include <fcntl.h> #include <netconfig.h>
*** 101,113 **** static int recvucred(int); static int anonmlp(int); static void add_to_poll_list(int, struct netconfig *); static char *serv_name_to_port_name(char *); static int bind_to_proto(char *, char *, struct netbuf **, ! struct netconfig **); static int bind_to_provider(char *, char *, struct netbuf **, ! struct netconfig **); static void conn_close_oldest(void); static boolean_t conn_get(int, struct netconfig *, struct conn_ind **); static void cots_listen_event(int, int); static int discon_get(int, struct netconfig *, struct conn_ind **); static int do_poll_clts_action(int, int); --- 99,111 ---- static int recvucred(int); static int anonmlp(int); static void add_to_poll_list(int, struct netconfig *); static char *serv_name_to_port_name(char *); static int bind_to_proto(char *, char *, struct netbuf **, ! struct netconfig **, int, int); static int bind_to_provider(char *, char *, struct netbuf **, ! struct netconfig **, int, int); static void conn_close_oldest(void); static boolean_t conn_get(int, struct netconfig *, struct conn_ind **); static void cots_listen_event(int, int); static int discon_get(int, struct netconfig *, struct conn_ind **); static int do_poll_clts_action(int, int);
*** 119,128 **** --- 117,127 ---- static struct pollfd *poll_array; static struct conn_entry *conn_polled; static int num_conns; /* Current number of connections */ int (*Mysvc4)(int, struct netbuf *, struct netconfig *, int, struct netbuf *); + static int setopt(int fd, int level, int name, int value); extern bool_t __pmap_set(const rpcprog_t program, const rpcvers_t version, const struct netconfig *nconf, const struct netbuf *address); /*
*** 238,250 **** } return (0); } int nfslib_bindit(struct netconfig *nconf, struct netbuf **addr, ! struct nd_hostserv *hs, int backlog) { int fd; struct t_bind *ntb; struct t_bind tb; struct nd_addrlist *addrlist; --- 237,268 ---- } return (0); } + static int + nfslib_set_sockbuf(int fd, int which, int val) + { + if ((which != SO_RCVBUF) && (which != SO_SNDBUF)) + return (-1); + + syslog(LOG_DEBUG, "Set %s option to %d", + ((which == SO_RCVBUF) ? "SO_RCVBUF" : "SO_SNDBUF"), val); + + if (setopt(fd, SOL_SOCKET, which, val) < 0) { + syslog(LOG_ERR, "couldn't set %s to %d - t_errno = %d", + ((which == SO_RCVBUF) ? "SO_RCVBUF" : "SO_SNDBUF"), + val, t_errno); + syslog(LOG_ERR, "Check and increase system-wide tcp_max_buf"); + return (-1); + } + return (0); + } + int nfslib_bindit(struct netconfig *nconf, struct netbuf **addr, ! struct nd_hostserv *hs, int backlog, int sndbufsz, int rcvbufsz) { int fd; struct t_bind *ntb; struct t_bind tb; struct nd_addrlist *addrlist;
*** 400,409 **** --- 418,432 ---- resp.flags != T_SUCCESS) { syslog(LOG_ERR, "couldn't set NODELAY option for proto %s: t_errno = %d, %m", nconf->nc_proto, t_errno); } + + if (sndbufsz > 0) + (void) nfslib_set_sockbuf(fd, SO_SNDBUF, sndbufsz); + if (rcvbufsz > 0) + (void) nfslib_set_sockbuf(fd, SO_RCVBUF, rcvbufsz); } return (fd); }
*** 475,489 **** } errno = error; } /* ! * Called to set up service over a particular transport. */ void ! do_one(char *provider, NETSELDECL(proto), struct protob *protobp0, ! int (*svc)(int, struct netbuf, struct netconfig *), int use_pmap) { register int sock; struct protob *protobp; struct netbuf *retaddr; struct netconfig *retnconf; --- 498,514 ---- } errno = error; } /* ! * Called to set up service over a particular transport also ! * set send and receive buffer size for transport connection. */ void ! do_one_setbuf(char *provider, NETSELDECL(proto), struct protob *protobp0, ! int (*svc)(int, struct netbuf, struct netconfig *), int use_pmap, ! int sndbufsz, int rcvbufsz) { register int sock; struct protob *protobp; struct netbuf *retaddr; struct netconfig *retnconf;
*** 492,505 **** int err; int l; if (provider) sock = bind_to_provider(provider, protobp0->serv, &retaddr, ! &retnconf); else sock = bind_to_proto(proto, protobp0->serv, &retaddr, ! &retnconf); if (sock == -1) { (void) syslog(LOG_ERR, "Cannot establish %s service over %s: transport setup problem.", protobp0->serv, provider ? provider : proto); --- 517,530 ---- int err; int l; if (provider) sock = bind_to_provider(provider, protobp0->serv, &retaddr, ! &retnconf, sndbufsz, rcvbufsz); else sock = bind_to_proto(proto, protobp0->serv, &retaddr, ! &retnconf, sndbufsz, rcvbufsz); if (sock == -1) { (void) syslog(LOG_ERR, "Cannot establish %s service over %s: transport setup problem.", protobp0->serv, provider ? provider : proto);
*** 580,596 **** * We successfully set up the server over this transport. * Add this descriptor to the one being polled on. */ add_to_poll_list(sock, retnconf); } /* ! * Set up the NFS service over all the available transports. * Returns -1 for failure, 0 for success. */ int ! do_all(struct protob *protobp, ! int (*svc)(int, struct netbuf, struct netconfig *), int use_pmap) { struct netconfig *nconf; NCONF_HANDLE *nc; int l; --- 605,624 ---- * We successfully set up the server over this transport. * Add this descriptor to the one being polled on. */ add_to_poll_list(sock, retnconf); } + /* ! * Set up the NFS service over all the available transports and ! * also set send and receive buffer size for transport connection. * Returns -1 for failure, 0 for success. */ int ! do_all_setbuf(struct protob *protobp, ! int (*svc)(int, struct netbuf, struct netconfig *), int use_pmap, ! int sndbufsz, int rcvbufsz) { struct netconfig *nconf; NCONF_HANDLE *nc; int l;
*** 603,620 **** if ((nconf->nc_flag & NC_VISIBLE) && strcmp(nconf->nc_protofmly, NC_LOOPBACK) != 0 && OK_TPI_TYPE(nconf) && (protobp->program != NFS4_CALLBACK || strncasecmp(nconf->nc_proto, NC_UDP, l) != 0)) ! do_one(nconf->nc_device, nconf->nc_proto, ! protobp, svc, use_pmap); } (void) endnetconfig(nc); return (0); } /* * poll on the open transport descriptors for events and errors. */ void poll_for_action(void) { --- 631,669 ---- if ((nconf->nc_flag & NC_VISIBLE) && strcmp(nconf->nc_protofmly, NC_LOOPBACK) != 0 && OK_TPI_TYPE(nconf) && (protobp->program != NFS4_CALLBACK || strncasecmp(nconf->nc_proto, NC_UDP, l) != 0)) ! do_one_setbuf(nconf->nc_device, nconf->nc_proto, ! protobp, svc, use_pmap, sndbufsz, rcvbufsz); } (void) endnetconfig(nc); return (0); } /* + * Called to set up service over a particular transport. + */ + void + do_one(char *provider, NETSELDECL(proto), struct protob *protobp0, + int (*svc)(int, struct netbuf, struct netconfig *), int use_pmap) + { + do_one_setbuf(provider, proto, protobp0, svc, use_pmap, 0, 0); + } + + /* + * Set up the NFS service over all the available transports. + * Returns -1 for failure, 0 for success. + */ + int + do_all(struct protob *protobp, + int (*svc)(int, struct netbuf, struct netconfig *), int use_pmap) + { + return (do_all_setbuf(protobp, svc, use_pmap, 0, 0)); + } + + /* * poll on the open transport descriptors for events and errors. */ void poll_for_action(void) {
*** 1575,1585 **** return ("unrecognized"); } static int bind_to_provider(char *provider, char *serv, struct netbuf **addr, ! struct netconfig **retnconf) { struct netconfig *nconf; NCONF_HANDLE *nc; struct nd_hostserv hs; --- 1624,1634 ---- return ("unrecognized"); } static int bind_to_provider(char *provider, char *serv, struct netbuf **addr, ! struct netconfig **retnconf, int sndbufsz, int rcvbufsz) { struct netconfig *nconf; NCONF_HANDLE *nc; struct nd_hostserv hs;
*** 1593,1603 **** while (nconf = getnetconfig(nc)) { if (OK_TPI_TYPE(nconf) && strcmp(nconf->nc_device, provider) == 0) { *retnconf = nconf; return (nfslib_bindit(nconf, addr, &hs, ! listen_backlog)); } } (void) endnetconfig(nc); syslog(LOG_ERR, "couldn't find netconfig entry for provider %s", --- 1642,1652 ---- while (nconf = getnetconfig(nc)) { if (OK_TPI_TYPE(nconf) && strcmp(nconf->nc_device, provider) == 0) { *retnconf = nconf; return (nfslib_bindit(nconf, addr, &hs, ! listen_backlog, sndbufsz, rcvbufsz)); } } (void) endnetconfig(nc); syslog(LOG_ERR, "couldn't find netconfig entry for provider %s",
*** 1605,1615 **** return (-1); } static int bind_to_proto(NETSELDECL(proto), char *serv, struct netbuf **addr, ! struct netconfig **retnconf) { struct netconfig *nconf; NCONF_HANDLE *nc = NULL; struct nd_hostserv hs; --- 1654,1664 ---- return (-1); } static int bind_to_proto(NETSELDECL(proto), char *serv, struct netbuf **addr, ! struct netconfig **retnconf, int sndbufsz, int rcvbufsz) { struct netconfig *nconf; NCONF_HANDLE *nc = NULL; struct nd_hostserv hs;
*** 1622,1632 **** } while (nconf = getnetconfig(nc)) { if (OK_TPI_TYPE(nconf) && NETSELEQ(nconf->nc_proto, proto)) { *retnconf = nconf; return (nfslib_bindit(nconf, addr, &hs, ! listen_backlog)); } } (void) endnetconfig(nc); syslog(LOG_ERR, "couldn't find netconfig entry for protocol %s", --- 1671,1681 ---- } while (nconf = getnetconfig(nc)) { if (OK_TPI_TYPE(nconf) && NETSELEQ(nconf->nc_proto, proto)) { *retnconf = nconf; return (nfslib_bindit(nconf, addr, &hs, ! listen_backlog, sndbufsz, rcvbufsz)); } } (void) endnetconfig(nc); syslog(LOG_ERR, "couldn't find netconfig entry for protocol %s",