--- old/usr/src/cmd/fs.d/nfs/lib/nfs_tbind.c Wed Jun 17 00:15:42 2009 +++ new/usr/src/cmd/fs.d/nfs/lib/nfs_tbind.c Wed Jun 17 00:15:42 2009 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -27,8 +27,6 @@ * nfs_tbind.c, common part for nfsd and lockd. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #define PORTMAP #include @@ -103,9 +101,9 @@ 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 **); + struct netconfig **, int, int); static int bind_to_provider(char *, char *, struct netbuf **, - struct netconfig **); + 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); @@ -121,6 +119,7 @@ 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); @@ -240,9 +239,28 @@ 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) + struct nd_hostserv *hs, int backlog, int sndbufsz, int rcvbufsz) { int fd; struct t_bind *ntb; @@ -402,6 +420,11 @@ "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); @@ -477,11 +500,13 @@ } /* - * Called to set up service over a particular transport. + * Called to set up service over a particular transport also + * set send and receive buffer size for transport connection. */ void -do_one(char *provider, NETSELDECL(proto), struct protob *protobp0, - int (*svc)(int, struct netbuf, struct netconfig *), int use_pmap) +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; @@ -494,10 +519,10 @@ if (provider) sock = bind_to_provider(provider, protobp0->serv, &retaddr, - &retnconf); + &retnconf, sndbufsz, rcvbufsz); else sock = bind_to_proto(proto, protobp0->serv, &retaddr, - &retnconf); + &retnconf, sndbufsz, rcvbufsz); if (sock == -1) { (void) syslog(LOG_ERR, @@ -582,13 +607,16 @@ */ add_to_poll_list(sock, retnconf); } + /* - * Set up the NFS service over all the available transports. + * 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(struct protob *protobp, - int (*svc)(int, struct netbuf, struct netconfig *), int use_pmap) +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; @@ -605,8 +633,8 @@ 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); + do_one_setbuf(nconf->nc_device, nconf->nc_proto, + protobp, svc, use_pmap, sndbufsz, rcvbufsz); } (void) endnetconfig(nc); return (0); @@ -613,6 +641,27 @@ } /* + * 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 @@ -1577,7 +1626,7 @@ static int bind_to_provider(char *provider, char *serv, struct netbuf **addr, - struct netconfig **retnconf) + struct netconfig **retnconf, int sndbufsz, int rcvbufsz) { struct netconfig *nconf; NCONF_HANDLE *nc; @@ -1595,7 +1644,7 @@ strcmp(nconf->nc_device, provider) == 0) { *retnconf = nconf; return (nfslib_bindit(nconf, addr, &hs, - listen_backlog)); + listen_backlog, sndbufsz, rcvbufsz)); } } (void) endnetconfig(nc); @@ -1607,7 +1656,7 @@ static int bind_to_proto(NETSELDECL(proto), char *serv, struct netbuf **addr, - struct netconfig **retnconf) + struct netconfig **retnconf, int sndbufsz, int rcvbufsz) { struct netconfig *nconf; NCONF_HANDLE *nc = NULL; @@ -1624,7 +1673,7 @@ if (OK_TPI_TYPE(nconf) && NETSELEQ(nconf->nc_proto, proto)) { *retnconf = nconf; return (nfslib_bindit(nconf, addr, &hs, - listen_backlog)); + listen_backlog, sndbufsz, rcvbufsz)); } } (void) endnetconfig(nc);