NIS performance patches
Jeff Bastian
jmbastia@ti.com
Thu Feb 5 17:22:00 GMT 2004
Thorsten,
I've used your patch with the latest glibc source RPM from RedHat for
RHEL3 and it compiled without any errors. I have it running on client
now, so all I need to do is find a NIS server and yank the network cord
and see if the client rebinds.
Thanks!
Jeff
Thorsten Kukuk wrote:
> Hi,
>
> On Sun, Jan 18, Thorsten Kukuk wrote:
>
>
>>On Thu, Jan 15, Thorsten Kukuk wrote:
>>
>>
>>>Sorry, here is now really the patch.
>>
>>And this patch does not work if an error occurs :(
>
>
> Attached is a new version of my patch, which works for me and my
> test cases. This version can be applied to the glibc CVS.
>
> Thorsten
>
>
>
> ------------------------------------------------------------------------
>
> 2004-02-03 Thorsten Kukuk <kukuk@suse.de>
>
> * nis/ypclnt.c (__yp_bind_client_create): New, small chunk
> of duplicated code from __yp_bind.
> (__yp_bind_file): New, binding dir code from __yp_bind.
> (__yp_bind_client_create): New, ypbind code from __yp_bind.
> (__ypclnt_call): New, make NIS query.
> (do_ypcall): At first use cached data, than try data from
> binding directory, after this ask ypbind for a working ypserv.
> Based on a patch from Jeff Bastian <jmbastia@ti.com> and
> Chris Barrera <cbarrera@ti.com>
>
> --- nis/ypclnt.c
> +++ nis/ypclnt.c 2004/02/03 15:16:33
> @@ -1,4 +1,4 @@
> -/* Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc.
> +/* Copyright (C) 1996-2001, 2002, 2003, 2004 Free Software Foundation, Inc.
> This file is part of the GNU C Library.
> Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
>
> @@ -53,14 +53,112 @@
> static dom_binding *__ypbindlist = NULL;
>
>
> +static void
> +__yp_bind_client_create (const char *domain, dom_binding *ysd,
> + struct ypbind_resp *ypbr)
> +{
> + ysd->dom_server_addr.sin_family = AF_INET;
> + memcpy (&ysd->dom_server_addr.sin_port,
> + ypbr->ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
> + sizeof (ysd->dom_server_addr.sin_port));
> + memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
> + ypbr->ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
> + sizeof (ysd->dom_server_addr.sin_addr.s_addr));
> + strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
> + ysd->dom_domain[YPMAXDOMAIN] = '\0';
> +
> + ysd->dom_socket = RPC_ANYSOCK;
> + ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
> + UDPTIMEOUT, &ysd->dom_socket);
> +
> + if (ysd->dom_client != NULL)
> + {
> + /* If the program exits, close the socket */
> + if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
> + perror ("fcntl: F_SETFD");
> + }
> +}
> +
> +static void
> +__yp_bind_file (const char *domain, dom_binding *ysd)
> +{
> + struct ypbind_resp ypbr;
> + char path[sizeof (BINDINGDIR) + strlen (domain) + 10];
> + struct iovec vec[2];
> + unsigned short port;
> + int fd;
> +
> + sprintf (path, "%s/%s.%d", BINDINGDIR, domain, YPBINDVERS);
> + fd = open (path, O_RDONLY);
> + if (fd >= 0)
> + {
> + /* We have a binding file and could save a RPC call */
> + vec[0].iov_base = &port;
> + vec[0].iov_len = sizeof (port);
> + vec[1].iov_base = &ypbr;
> + vec[1].iov_len = sizeof (ypbr);
> +
> + if (readv (fd, vec, 2) == sizeof (port) + sizeof (ypbr))
> + __yp_bind_client_create (domain, ysd, &ypbr);
> +
> + close (fd);
> + }
> +}
> +
> static int
> -__yp_bind (const char *domain, dom_binding **ypdb)
> +__yp_bind_ypbindprog (const char *domain, dom_binding *ysd)
> {
> struct sockaddr_in clnt_saddr;
> struct ypbind_resp ypbr;
> - dom_binding *ysd = NULL;
> int clnt_sock;
> CLIENT *client;
> +
> + memset (&clnt_saddr, '\0', sizeof clnt_saddr);
> + clnt_saddr.sin_family = AF_INET;
> + clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
> + clnt_sock = RPC_ANYSOCK;
> + client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
> + &clnt_sock, 0, 0);
> + if (client == NULL)
> + return YPERR_YPBIND;
> +
> + /* Check the port number -- should be < IPPORT_RESERVED.
> + If not, it's possible someone has registered a bogus
> + ypbind with the portmapper and is trying to trick us. */
> + if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED)
> + {
> + clnt_destroy (client);
> + return YPERR_YPBIND;
> + }
> +
> + if (clnt_call (client, YPBINDPROC_DOMAIN,
> + (xdrproc_t) xdr_domainname, (caddr_t) &domain,
> + (xdrproc_t) xdr_ypbind_resp,
> + (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS)
> + {
> + clnt_destroy (client);
> + return YPERR_YPBIND;
> + }
> +
> + clnt_destroy (client);
> +
> + if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
> + {
> + fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"),
> + ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error));
> + return YPERR_DOMAIN;
> + }
> + memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
> +
> + __yp_bind_client_create (domain, ysd, &ypbr);
> +
> + return YPERR_SUCCESS;
> +}
> +
> +static int
> +__yp_bind (const char *domain, dom_binding **ypdb)
> +{
> + dom_binding *ysd = NULL;
> int is_new = 0;
>
> if (domain == NULL || domain[0] == '\0')
> @@ -83,116 +181,20 @@
> }
>
> #if USE_BINDINGDIR
> - if (ysd->dom_client == NULL)
> - {
> /* Try binding dir at first if we have no binding */
> - char path[sizeof (BINDINGDIR) + strlen (domain) + 10];
> - struct iovec vec[2];
> - unsigned short port;
> - int fd;
> -
> - sprintf (path, "%s/%s.%d", BINDINGDIR, domain, YPBINDVERS);
> - fd = open (path, O_RDONLY);
> - if (fd >= 0)
> - {
> - /* We have a binding file and could save a RPC call */
> - vec[0].iov_base = &port;
> - vec[0].iov_len = sizeof (port);
> - vec[1].iov_base = &ypbr;
> - vec[1].iov_len = sizeof (ypbr);
> -
> - if (readv (fd, vec, 2) == sizeof (port) + sizeof (ypbr))
> - {
> - ysd->dom_server_addr.sin_family = AF_INET;
> - memcpy (&ysd->dom_server_addr.sin_port,
> - ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
> - sizeof (ysd->dom_server_addr.sin_port));
> - memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
> - ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
> - sizeof (ysd->dom_server_addr.sin_addr.s_addr));
> - strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
> - ysd->dom_domain[YPMAXDOMAIN] = '\0';
> -
> - ysd->dom_socket = RPC_ANYSOCK;
> - ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG,
> - YPVERS, UDPTIMEOUT,
> - &ysd->dom_socket);
> -
> - if (ysd->dom_client != NULL)
> - /* If the program exits, close the socket */
> - if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
> - perror ("fcntl: F_SETFD");
> - }
> - close (fd);
> - }
> - }
> + if (ysd->dom_client == NULL)
> + __yp_bind_file (domain, ysd);
> #endif /* USE_BINDINGDIR */
>
> if (ysd->dom_client == NULL)
> {
> - memset (&clnt_saddr, '\0', sizeof clnt_saddr);
> - clnt_saddr.sin_family = AF_INET;
> - clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
> - clnt_sock = RPC_ANYSOCK;
> - client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
> - &clnt_sock, 0, 0);
> - if (client == NULL)
> - {
> - if (is_new)
> - free (ysd);
> - return YPERR_YPBIND;
> - }
> - /* Check the port number -- should be < IPPORT_RESERVED.
> - If not, it's possible someone has registered a bogus
> - ypbind with the portmapper and is trying to trick us. */
> - if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED)
> - {
> - clnt_destroy (client);
> - if (is_new)
> - free (ysd);
> - return YPERR_YPBIND;
> - }
> -
> - if (clnt_call (client, YPBINDPROC_DOMAIN,
> - (xdrproc_t) xdr_domainname, (caddr_t) &domain,
> - (xdrproc_t) xdr_ypbind_resp,
> - (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS)
> + int retval = __yp_bind_ypbindprog (domain, ysd);
> + if (retval != YPERR_SUCCESS)
> {
> - clnt_destroy (client);
> if (is_new)
> free (ysd);
> - return YPERR_YPBIND;
> + return retval;
> }
> -
> - clnt_destroy (client);
> -
> - if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
> - {
> - fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"),
> - ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error));
> - if (is_new)
> - free (ysd);
> - return YPERR_DOMAIN;
> - }
> - memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
> - ysd->dom_server_addr.sin_family = AF_INET;
> - memcpy (&ysd->dom_server_addr.sin_port,
> - ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
> - sizeof (ysd->dom_server_addr.sin_port));
> - memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
> - ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
> - sizeof (ysd->dom_server_addr.sin_addr.s_addr));
> - strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
> - ysd->dom_domain[YPMAXDOMAIN] = '\0';
> -
> - ysd->dom_socket = RPC_ANYSOCK;
> - ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
> - UDPTIMEOUT, &ysd->dom_socket);
> -
> - if (ysd->dom_client != NULL)
> - /* If the program exits, close the socket */
> - if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
> - perror ("fcntl: F_SETFD");
> }
>
> if (ysd->dom_client == NULL)
> @@ -215,7 +217,6 @@
> __yp_unbind (dom_binding *ydb)
> {
> clnt_destroy (ydb->dom_client);
> - ydb->dom_client = NULL;
> free (ydb);
> }
>
> @@ -273,16 +274,36 @@
> }
>
> static int
> +__ypclnt_call (const char *domain, u_long prog, xdrproc_t xargs,
> + caddr_t req, xdrproc_t xres, caddr_t resp, dom_binding **ydb,
> + int print_error)
> +{
> + enum clnt_stat result;
> +
> + result = clnt_call ((*ydb)->dom_client, prog,
> + xargs, req, xres, resp, RPCTIMEOUT);
> +
> + if (result != RPC_SUCCESS)
> + {
> + /* We don't print an error message, if we try our old,
> + cached data. Only print this for data, which should work. */
> + if (print_error)
> + clnt_perror ((*ydb)->dom_client, "do_ypcall: clnt_call");
> +
> + return YPERR_RPC;
> + }
> +
> + return YPERR_SUCCESS;
> +}
> +
> +static int
> do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
> caddr_t req, xdrproc_t xres, caddr_t resp)
> {
> - dom_binding *ydb = NULL;
> - bool_t use_ypbindlist = FALSE;
> - int try, status;
> - enum clnt_stat result;
> + dom_binding *ydb;
> + int status;
> int saved_errno = errno;
>
> - try = 0;
> status = YPERR_YPERR;
>
> __libc_lock_lock (ypbindlist_lock);
> @@ -296,60 +317,53 @@
> ydb = ydb->dom_pnext;
> }
> if (ydb != NULL)
> - use_ypbindlist = TRUE;
> - else
> - __libc_lock_unlock (ypbindlist_lock);
> + {
> + if (__yp_bind (domain, &ydb) == 0)
> + {
> + /* Call server, print no error message, do not unbind. */
> + status = __ypclnt_call (domain, prog, xargs, req, xres,
> + resp, &ydb, 0);
> + if (status == YPERR_SUCCESS)
> + {
> + __set_errno (saved_errno);
> + return status;
> + }
> + }
> + /* We use ypbindlist, and the old cached data is
> + invalid. unbind now and create a new binding */
> + yp_unbind_locked (domain);
> + }
> + __libc_lock_unlock (ypbindlist_lock);
> }
> else
> __libc_lock_unlock (ypbindlist_lock);
>
> - while (try < MAXTRIES && status != YPERR_SUCCESS)
> + /* First try with cached data failed. Now try to get
> + current data from the system. */
> + ydb = NULL;
> + if (__yp_bind (domain, &ydb) == 0)
> {
> - if (__yp_bind (domain, &ydb) != 0)
> - {
> - if (use_ypbindlist)
> - __libc_lock_unlock (ypbindlist_lock);
> - __set_errno (saved_errno);
> - return YPERR_DOMAIN;
> - }
> -
> - result = clnt_call (ydb->dom_client, prog,
> - xargs, req, xres, resp, RPCTIMEOUT);
> -
> - if (result != RPC_SUCCESS)
> - {
> - /* Don't print the error message on the first try. It
> - could be that we use cached data which is now invalid. */
> - if (try != 0)
> - clnt_perror (ydb->dom_client, "do_ypcall: clnt_call");
> -
> - if (use_ypbindlist)
> - {
> - /* We use ypbindlist, and the old cached data is
> - invalid. unbind now and create a new binding */
> - yp_unbind_locked (domain);
> - __libc_lock_unlock (ypbindlist_lock);
> - use_ypbindlist = FALSE;
> - }
> - else
> - __yp_unbind (ydb);
> + status = __ypclnt_call (domain, prog, xargs, req, xres,
> + resp, &ydb, 1);
> + __yp_unbind (ydb);
> + }
>
> - ydb = NULL;
> - status = YPERR_RPC;
> +#if USE_BINDINGDIR
> + /* If we support binding dir data, we have a third chance:
> + Ask ypbind. */
> + if (status != YPERR_SUCCESS)
> + {
> + ydb = calloc (1, sizeof (dom_binding));
> + if (__yp_bind_ypbindprog (domain, ydb) == YPERR_SUCCESS)
> + {
> + status = __ypclnt_call (domain, prog, xargs, req, xres,
> + resp, &ydb, 1);
> + __yp_unbind (ydb);
> }
> else
> - status = YPERR_SUCCESS;
> -
> - try++;
> + free (ydb);
> }
> - if (use_ypbindlist)
> - {
> - __libc_lock_unlock (ypbindlist_lock);
> - use_ypbindlist = FALSE;
> - }
> - else
> - if (ydb != NULL)
> - __yp_unbind (ydb);
> +#endif
>
> __set_errno (saved_errno);
>
More information about the Libc-alpha
mailing list