diff options
author | Ulrich Drepper <drepper@redhat.com> | 2004-12-22 20:10:10 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2004-12-22 20:10:10 +0000 |
commit | a334319f6530564d22e775935d9c91663623a1b4 (patch) | |
tree | b5877475619e4c938e98757d518bb1e9cbead751 /nscd/nscd_helper.c | |
parent | 0ecb606cb6cf65de1d9fc8a919bceb4be476c602 (diff) | |
download | glibc-a334319f6530564d22e775935d9c91663623a1b4.zip glibc-a334319f6530564d22e775935d9c91663623a1b4.tar.gz glibc-a334319f6530564d22e775935d9c91663623a1b4.tar.bz2 |
(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
Diffstat (limited to 'nscd/nscd_helper.c')
-rw-r--r-- | nscd/nscd_helper.c | 253 |
1 files changed, 64 insertions, 189 deletions
diff --git a/nscd/nscd_helper.c b/nscd/nscd_helper.c index 71ea53e..0e16cb8 100644 --- a/nscd/nscd_helper.c +++ b/nscd/nscd_helper.c @@ -1,5 +1,4 @@ -/* Copyright (C) 1998-2002,2003,2004,2005,2006,2007 - Free Software Foundation, Inc. +/* Copyright (C) 1998-2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. @@ -22,14 +21,11 @@ #include <errno.h> #include <fcntl.h> #include <stdbool.h> -#include <string.h> -#include <time.h> #include <unistd.h> #include <sys/mman.h> #include <sys/poll.h> #include <sys/socket.h> #include <sys/stat.h> -#include <sys/time.h> #include <sys/uio.h> #include <sys/un.h> #include <not-cancel.h> @@ -38,64 +34,6 @@ #include "nscd-client.h" -ssize_t -__readall (int fd, void *buf, size_t len) -{ - size_t n = len; - ssize_t ret; - do - { - ret = TEMP_FAILURE_RETRY (__read (fd, buf, n)); - if (ret <= 0) - break; - buf = (char *) buf + ret; - n -= ret; - } - while (n > 0); - return ret < 0 ? ret : len - n; -} - - -ssize_t -__readvall (int fd, const struct iovec *iov, int iovcnt) -{ - ssize_t ret = TEMP_FAILURE_RETRY (__readv (fd, iov, iovcnt)); - if (ret <= 0) - return ret; - - size_t total = 0; - for (int i = 0; i < iovcnt; ++i) - total += iov[i].iov_len; - - if (ret < total) - { - struct iovec iov_buf[iovcnt]; - ssize_t r = ret; - - struct iovec *iovp = memcpy (iov_buf, iov, iovcnt * sizeof (*iov)); - do - { - while (iovp->iov_len <= r) - { - r -= iovp->iov_len; - --iovcnt; - ++iovp; - } - iovp->iov_base = (char *) iovp->iov_base + r; - iovp->iov_len -= r; - r = TEMP_FAILURE_RETRY (__readv (fd, iovp, iovcnt)); - if (r <= 0) - break; - ret += r; - } - while (ret < total); - if (r < 0) - ret = r; - } - return ret; -} - - static int open_socket (void) { @@ -139,36 +77,6 @@ __nscd_unmap (struct mapped_database *mapped) } -static int -wait_on_socket (int sock) -{ - struct pollfd fds[1]; - fds[0].fd = sock; - fds[0].events = POLLIN | POLLERR | POLLHUP; - int n = __poll (fds, 1, 5 * 1000); - if (n == -1 && __builtin_expect (errno == EINTR, 0)) - { - /* Handle the case where the poll() call is interrupted by a - signal. We cannot just use TEMP_FAILURE_RETRY since it might - lead to infinite loops. */ - struct timeval now; - (void) __gettimeofday (&now, NULL); - long int end = (now.tv_sec + 5) * 1000 + (now.tv_usec + 500) / 1000; - while (1) - { - long int timeout = end - (now.tv_sec * 1000 - + (now.tv_usec + 500) / 1000); - n = __poll (fds, 1, timeout); - if (n != -1 || errno != EINTR) - break; - (void) __gettimeofday (&now, NULL); - } - } - - return n; -} - - /* Try to get a file descriptor for the shared meory segment containing the database. */ static struct mapped_database * @@ -178,115 +86,102 @@ get_mapping (request_type type, const char *key, struct mapped_database *result = NO_MAPPING; #ifdef SCM_RIGHTS const size_t keylen = strlen (key) + 1; + char resdata[keylen]; int saved_errno = errno; int mapfd = -1; /* Send the request. */ - struct - { - request_header req; - char key[keylen]; - } reqdata; - size_t real_sizeof_reqdata = sizeof (request_header) + keylen; + struct iovec iov[2]; + request_header req; int sock = open_socket (); if (sock < 0) goto out; - reqdata.req.version = NSCD_VERSION; - reqdata.req.type = type; - reqdata.req.key_len = keylen; - memcpy (reqdata.key, key, keylen); - -# ifndef MSG_NOSIGNAL -# define MSG_NOSIGNAL 0 -# endif - if (__builtin_expect (TEMP_FAILURE_RETRY (__send (sock, &reqdata, - real_sizeof_reqdata, - MSG_NOSIGNAL)) - != real_sizeof_reqdata, 0)) + req.version = NSCD_VERSION; + req.type = type; + req.key_len = keylen; + + iov[0].iov_base = &req; + iov[0].iov_len = sizeof (req); + iov[1].iov_base = (void *) key; + iov[1].iov_len = keylen; + + if (TEMP_FAILURE_RETRY (__writev (sock, iov, 2)) + != iov[0].iov_len + iov[1].iov_len) /* We cannot even write the request. */ goto out_close2; /* Room for the data sent along with the file descriptor. We expect the key name back. */ -# define resdata reqdata.key - struct iovec iov[1]; iov[0].iov_base = resdata; iov[0].iov_len = keylen; - union - { - struct cmsghdr hdr; - char bytes[CMSG_SPACE (sizeof (int))]; - } buf; + char buf[CMSG_SPACE (sizeof (int))]; struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1, - .msg_control = buf.bytes, - .msg_controllen = sizeof (buf) }; + .msg_control = buf, .msg_controllen = sizeof (buf) }; struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN (sizeof (int)); - /* This access is well-aligned since BUF is correctly aligned for an - int and CMSG_DATA preserves this alignment. */ *(int *) CMSG_DATA (cmsg) = -1; msg.msg_controllen = cmsg->cmsg_len; - if (wait_on_socket (sock) <= 0) - goto out_close2; - - if (__builtin_expect (TEMP_FAILURE_RETRY (__recvmsg (sock, &msg, 0)) - != keylen, 0)) + struct pollfd fds[1]; + fds[0].fd = sock; + fds[0].events = POLLIN | POLLERR | POLLHUP; + if (__poll (fds, 1, 5 * 1000) <= 0) + /* Failure or timeout. */ goto out_close2; - if (__builtin_expect (CMSG_FIRSTHDR (&msg) == NULL - || (CMSG_FIRSTHDR (&msg)->cmsg_len - != CMSG_LEN (sizeof (int))), 0)) + if (TEMP_FAILURE_RETRY (__recvmsg (sock, &msg, 0)) != keylen) goto out_close2; mapfd = *(int *) CMSG_DATA (cmsg); + if (CMSG_FIRSTHDR (&msg)->cmsg_len != CMSG_LEN (sizeof (int))) + goto out_close; + struct stat64 st; - if (__builtin_expect (strcmp (resdata, key) != 0, 0) - || __builtin_expect (fstat64 (mapfd, &st) != 0, 0) - || __builtin_expect (st.st_size < sizeof (struct database_pers_head), 0)) + if (strcmp (resdata, key) != 0 + || fstat64 (mapfd, &st) != 0 + || st.st_size < sizeof (struct database_pers_head)) goto out_close; struct database_pers_head head; - if (__builtin_expect (TEMP_FAILURE_RETRY (__pread (mapfd, &head, - sizeof (head), 0)) - != sizeof (head), 0)) + if (TEMP_FAILURE_RETRY (__pread (mapfd, &head, sizeof (head), 0)) + != sizeof (head)) goto out_close; - if (__builtin_expect (head.version != DB_VERSION, 0) - || __builtin_expect (head.header_size != sizeof (head), 0) + if (head.version != DB_VERSION || head.header_size != sizeof (head) /* This really should not happen but who knows, maybe the update thread got stuck. */ - || __builtin_expect (! head.nscd_certainly_running - && head.timestamp + MAPPING_TIMEOUT < time (NULL), - 0)) + || (! head.nscd_certainly_running + && head.timestamp + MAPPING_TIMEOUT < time (NULL))) goto out_close; size_t size = (sizeof (head) + roundup (head.module * sizeof (ref_t), ALIGN) + head.data_size); - if (__builtin_expect (st.st_size < size, 0)) + if (st.st_size < size) goto out_close; /* The file is large enough, map it now. */ void *mapping = __mmap (NULL, size, PROT_READ, MAP_SHARED, mapfd, 0); - if (__builtin_expect (mapping != MAP_FAILED, 1)) + if (mapping != MAP_FAILED) { /* Allocate a record for the mapping. */ - struct mapped_database *newp = malloc (sizeof (*newp)); + struct mapped_database *newp; + + newp = malloc (sizeof (*newp)); if (newp == NULL) { /* Ugh, after all we went through the memory allocation failed. */ - __munmap (mapping, size); + __munmap (result, size); goto out_close; } @@ -294,7 +189,6 @@ get_mapping (request_type type, const char *key, newp->data = ((char *) mapping + head.header_size + roundup (head.module * sizeof (ref_t), ALIGN)); newp->mapsize = size; - newp->datasize = head.data_size; /* Set counter to 1 to show it is usable. */ newp->counter = 1; @@ -321,18 +215,17 @@ get_mapping (request_type type, const char *key, struct mapped_database * __nscd_get_map_ref (request_type type, const char *name, - volatile struct locked_map_ptr *mapptr, int *gc_cyclep) + struct locked_map_ptr *mapptr, int *gc_cyclep) { struct mapped_database *cur = mapptr->mapped; if (cur == NO_MAPPING) return cur; int cnt = 0; - while (__builtin_expect (atomic_compare_and_exchange_val_acq (&mapptr->lock, - 1, 0) != 0, 0)) + while (atomic_compare_and_exchange_val_acq (&mapptr->lock, 1, 0) != 0) { // XXX Best number of rounds? - if (__builtin_expect (++cnt > 5, 0)) + if (++cnt > 5) return NO_MAPPING; atomic_delay (); @@ -345,10 +238,8 @@ __nscd_get_map_ref (request_type type, const char *name, /* If not mapped or timestamp not updated, request new map. */ if (cur == NULL || (cur->head->nscd_certainly_running == 0 - && cur->head->timestamp + MAPPING_TIMEOUT < time (NULL)) - || cur->head->data_size > cur->datasize) - cur = get_mapping (type, name, - (struct mapped_database **) &mapptr->mapped); + && cur->head->timestamp + MAPPING_TIMEOUT < time (NULL))) + cur = get_mapping (type, name, &mapptr->mapped); if (__builtin_expect (cur != NO_MAPPING, 1)) { @@ -366,50 +257,28 @@ __nscd_get_map_ref (request_type type, const char *name, } -/* Don't return const struct datahead *, as eventhough the record - is normally constant, it can change arbitrarily during nscd - garbage collection. */ -struct datahead * +const struct datahead * __nscd_cache_search (request_type type, const char *key, size_t keylen, const struct mapped_database *mapped) { unsigned long int hash = __nis_hash (key, keylen) % mapped->head->module; - size_t datasize = mapped->datasize; ref_t work = mapped->head->array[hash]; - while (work != ENDREF && work + sizeof (struct hashentry) <= datasize) + while (work != ENDREF) { struct hashentry *here = (struct hashentry *) (mapped->data + work); -#ifndef _STRING_ARCH_unaligned - /* Although during garbage collection when moving struct hashentry - records around we first copy from old to new location and then - adjust pointer from previous hashentry to it, there is no barrier - between those memory writes. It is very unlikely to hit it, - so check alignment only if a misaligned load can crash the - application. */ - if ((uintptr_t) here & (__alignof__ (*here) - 1)) - return NULL; -#endif - - if (type == here->type - && keylen == here->len - && here->key + keylen <= datasize - && memcmp (key, mapped->data + here->key, keylen) == 0 - && here->packet + sizeof (struct datahead) <= datasize) + if (type == here->type && keylen == here->len + && memcmp (key, mapped->data + here->key, keylen) == 0) { /* We found the entry. Increment the appropriate counter. */ - struct datahead *dh + const struct datahead *dh = (struct datahead *) (mapped->data + here->packet); -#ifndef _STRING_ARCH_unaligned - if ((uintptr_t) dh & (__alignof__ (*dh) - 1)) - return NULL; -#endif - /* See whether we must ignore the entry or whether something is wrong because garbage collection is in progress. */ - if (dh->usable && here->packet + dh->allocsize <= datasize) + if (dh->usable && ((char *) dh + dh->allocsize + <= (char *) mapped->head + mapped->mapsize)) return dh; } @@ -442,13 +311,19 @@ __nscd_open_socket (const char *key, size_t keylen, request_type type, vec[1].iov_len = keylen; ssize_t nbytes = TEMP_FAILURE_RETRY (__writev (sock, vec, 2)); - if (nbytes == (ssize_t) (sizeof (request_header) + keylen) - /* Wait for data. */ - && wait_on_socket (sock) > 0) + if (nbytes == (ssize_t) (sizeof (request_header) + keylen)) { - nbytes = TEMP_FAILURE_RETRY (__read (sock, response, responselen)); - if (nbytes == (ssize_t) responselen) - return sock; + /* Wait for data. */ + struct pollfd fds[1]; + fds[0].fd = sock; + fds[0].events = POLLIN | POLLERR | POLLHUP; + if (__poll (fds, 1, 5 * 1000) > 0) + { + nbytes = TEMP_FAILURE_RETRY (__read (sock, response, + responselen)); + if (nbytes == (ssize_t) responselen) + return sock; + } } close_not_cancel_no_status (sock); |