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",