Date: Tue, 3 Apr 2001 18:39:50 +0200 (CEST) From: bg@sics.se To: FreeBSD-gnats-submit@freebsd.org Cc: bg@sics.se Subject: misc/26320: mountd breaks IRIX automounter Message-ID: <200104031639.f33Gdoa09283@bg.sics.se>
next in thread | raw e-mail | index | archive | help
>Number: 26320 >Category: misc >Synopsis: mountd breaks IRIX automounter >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Apr 03 09:40:00 PDT 2001 >Closed-Date: >Last-Modified: >Originator: Bjoern Groenvall >Release: FreeBSD 4.2-RELEASE i386 >Organization: SICS >Environment: NFS servers running FreeBSD 3.5-RELEASE or FreeBSD 4.2-RELEASE >Description: This problem really stems from a poorly designed mount protocol. When using ONC/RPC over UDP, RPC requests and responses are limited to 8kbytes of data. If a RPC response can not fit into that limited space the RPC will fail. The mountd protocol has a procedure MOUNTPROC_EXPORT that returns a list of all exported file systems and which machines are allowed to import it. If a server has many clients and exports many file systems this RPC reply will no longer fit into 8kbytes! Fortunately, only the list of exported file systems is relevant to programs such as the automounter. It is thus possible to return an abbreviated reply that uses a placeholder for the hosts lists. >How-To-Repeat: Set up a FreeBSD NFS file server and export many file systems to many hosts. Verify that the output from showmount -e your.nfs.server is really long (longer than 8k). From a IRIX host, try ls /hosts/your.file.server/. The ls will eventually fail. On the file server you will find a syslog entry "can't send reply". >Fix: The fix below first try to send a regular RPC reply, only when this fails, an abbreviated reply is sent. The fix has been verified on 3.5 and 4.2 hosts. --- mountd.c.ORIG Tue Nov 23 00:03:59 1999 +++ mountd.c Mon Apr 2 18:43:17 2001 @@ -191,11 +191,12 @@ void nextfield __P((char **, char **)); void out_of_mem __P((void)); void parsecred __P((char *, struct ucred *)); -int put_exlist __P((struct dirlist *, XDR *, struct dirlist *, int *)); +int put_exlist __P((struct dirlist *, XDR *, struct dirlist *, int *,int)); int scan_tree __P((struct dirlist *, u_int32_t)); static void usage __P((void)); int xdr_dir __P((XDR *, char *)); int xdr_explist __P((XDR *, caddr_t)); +int xdr_explist_brief __P((XDR *, caddr_t)); int xdr_fhs __P((XDR *, caddr_t)); int xdr_mlist __P((XDR *, caddr_t)); @@ -542,7 +543,8 @@ return; case RPCMNT_EXPORT: if (!svc_sendreply(transp, xdr_explist, (caddr_t)NULL)) - syslog(LOG_ERR, "can't send reply"); + if (!svc_sendreply(transp, xdr_explist_brief, (caddr_t)NULL)) + syslog(LOG_ERR, "can't send reply"); if (log) syslog(LOG_NOTICE, "export request succeeded from %s", @@ -630,9 +632,10 @@ * Xdr conversion for export list */ int -xdr_explist(xdrsp, cp) +xdr_explist_common(xdrsp, cp, brief) XDR *xdrsp; caddr_t cp; + int brief; { struct exportlist *ep; int false = 0; @@ -645,11 +648,12 @@ ep = exphead; while (ep) { putdef = 0; - if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir, &putdef)) + if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir, + &putdef, brief)) goto errout; if (ep->ex_defdir && putdef == 0 && put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL, - &putdef)) + &putdef, brief)) goto errout; ep = ep->ex_next; } @@ -667,11 +671,12 @@ * directory paths. */ int -put_exlist(dp, xdrsp, adp, putdefp) +put_exlist(dp, xdrsp, adp, putdefp, brief) struct dirlist *dp; XDR *xdrsp; struct dirlist *adp; int *putdefp; + int brief; { struct grouplist *grp; struct hostlist *hp; @@ -681,7 +686,7 @@ char *strp; if (dp) { - if (put_exlist(dp->dp_left, xdrsp, adp, putdefp)) + if (put_exlist(dp->dp_left, xdrsp, adp, putdefp, brief)) return (1); if (!xdr_bool(xdrsp, &true)) return (1); @@ -692,7 +697,13 @@ gotalldir = 1; *putdefp = 1; } - if ((dp->dp_flag & DP_DEFSET) == 0 && + if (brief) { + if (!xdr_bool(xdrsp, &true)) + return (1); + strp = "(...)"; + if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) + return (1); + } else if ((dp->dp_flag & DP_DEFSET) == 0 && (gotalldir == 0 || (adp->dp_flag & DP_DEFSET) == 0)) { hp = dp->dp_hosts; while (hp) { @@ -721,10 +732,26 @@ } if (!xdr_bool(xdrsp, &false)) return (1); - if (put_exlist(dp->dp_right, xdrsp, adp, putdefp)) + if (put_exlist(dp->dp_right, xdrsp, adp, putdefp, brief)) return (1); } return (0); +} + +int +xdr_explist(xdrsp, cp) + XDR *xdrsp; + caddr_t cp; +{ + return xdr_explist_common(xdrsp, cp, 0 /* !brief */); +} + +int +xdr_explist_brief(xdrsp, cp) + XDR *xdrsp; + caddr_t cp; +{ + return xdr_explist_common(xdrsp, cp, 1 /* brief */); } #define LINESIZ 10240 >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200104031639.f33Gdoa09283>