2008-06-12 Ulrich Drepper <drepper@redhat.com> * nscd/grpcache.c (cache_addgr): Correctly compute size of fixed-size portion of the record. * nscd/servicescache.c (cache_addserv): Likewise. * nscd/pwdcache.c (cache_addpw): Likewise. * nscd/initgrcache.c (addinitgroupsX): Likewise. 2008-06-11 Ulrich Drepper <drepper@redhat.com> * nscd/mem.c (gc): Initialize obstack earlier so that if we jump out we don't use uninitialized memory. * nscd/hstcache.c (cache_addhst): Send correct number of bytes to the client. 2008-06-03 Jakub Jelinek <jakub@redhat.com> * nscd/nscd_getserv_r.c (__nscd_getservbyport_r): Pass cp instead of portstr to nscd_getserv_r. Patch by Roman Kagan <rkagan@mail.ru>. 2008-05-18 Ulrich Drepper <drepper@redhat.com> * nscd/cache.c (cache_add): Take additional parameter specifying whether this is in response of a cache refill. Check alignment of package data. Revamp waking of pruning thread. (prune_cache): Small optimization. * nscd/nscd.h: Adjust cache_add prototypes. * nscd/aicache.c: Adjust cache_add calls. * nscd/grpcache.c: Likewise. * nscd/hstcache.c: Likewise. * nscd/initgrcache.c: Likewise. * nscd/pwdcache.c: Likewise. * nscd/servicescache.c: Likewise. * nscd/connections.c (restart): Really disable cache use before exec attempt. If it fails, reenable cache. (nscd_run_prune): Initialize wakeup_time. After wakeup, set wakeup time to max to be able to notice concurrent cache additions. Unlock prune_lock while performing gc. Afterwards compute wakeup time with current wakeup_time value in mind. 2008-05-17 Ulrich Drepper <drepper@redhat.com> * nscd/mem.c (gc): Avoid stack overflow when allocating move list. * nscd/mem.c (gc): Correctly determine highest used array element in mark. * nscd/mem.c (markrange): Add assert to check entries are all aligned. Small cleanup in bitmap use. * nscd/nscd.h (mem_in_flight): Replace blockaddr field with blockoff of type nscd_ssize_t. * nscd/mem.c (gc): Simplify markrange call for on-flight blocks. (mempoll_alloc): Record block offset and not address. * nscd/mem.c (gc): Fix test for stack overuse. 2008-05-10 Ulrich Drepper <drepper@redhat.com> * nscd/cache.c (cache_add): Before returning with failure and this is the first use of the record, mark it as unusable. * nscd/aicache.c: Don't touch the dataset after cache_add returns reporting a failure. * nscd/grpcache.c: Likewise * nscd/hstcache.c: Likewise. * nscd/initgrcache.c: Likewise. * nscd/pwdcache.c: Likewise. * nscd/servicecache.c: Likewise. 2008-04-22 Jakub Jelinek <jakub@redhat.com> * nscd/Makefile (nscd-cflags): Set back to -fpie. * nscd/nscd.h (mem_in_flight): Add attribute_tls_model_ie. * nscd/connections.c (mem_in_flight): Likewise. * nscd/nscd.h (dbs): Make hidden. 2008-04-15 Ulrich Drepper <drepper@redhat.com> [BZ #5381] * nscd/nscd.h: Define enum in_flight, mem_in_flight, and mem_in_flight_list variables. Add new parameter to mempool_alloc prototype. * nscd/mem.c (mempool_alloc): Take additional parameter. Initialize appropriate mem_in_flight element. (gc): Take allocations which have not yet been committed to the database into account. * nscd/cache.c (cache_add): Add new parameter to mempool_alloc call. Reset mem_in_flight before returning. * nscd/connections.c (nscd_run_worker): Initialize mem_in_flight and cue it up in mem_in_flight_list. * nscd/aicache.c: Adjust mempool_alloc call. * nscd/grpcache.c: Likewise. * nscd/hstcache.c: Likewise. * nscd/initgrcache.c: Likewise. * nscd/pwdcache.c: Likewise. * nscd/servicescache.c: Likewise. * nscd/Makefile (nscd-flags): Until ld is fixed, use -fpic instead of -fpie. * nscd/connections.c (handle_request): Provide better error message in case SELinux forbids the service. =================================================================== RCS file: /cvs/glibc/libc/nscd/Makefile,v retrieving revision 1.54 retrieving revision 1.55 diff -u -r1.54 -r1.55 --- libc/nscd/Makefile 2007/10/30 00:45:48 1.54 +++ libc/nscd/Makefile 2008/04/19 16:40:58 1.55 @@ -1,4 +1,4 @@ -# Copyright (C) 1998,2000,2002,2003,2004,2005,2006,2007 +# Copyright (C) 1998,2000,2002,2003,2004,2005,2006,2007,2008 # Free Software Foundation, Inc. # This file is part of the GNU C Library. @@ -90,7 +90,8 @@ nscd-cflags = -DIS_IN_nscd=1 -D_FORTIFY_SOURCE=2 ifeq (yesyes,$(have-fpie)$(build-shared)) -nscd-cflags += -fpie +#nscd-cflags += -fpie +nscd-cflags += -fpic endif ifeq (yes,$(have-ssp)) nscd-cflags += -fstack-protector =================================================================== RCS file: /cvs/glibc/libc/nscd/nscd.h,v retrieving revision 1.33 retrieving revision 1.34 diff -u -r1.33 -r1.34 --- libc/nscd/nscd.h 2008/03/04 01:53:25 1.33 +++ libc/nscd/nscd.h 2008/04/19 16:41:20 1.34 @@ -181,6 +181,31 @@ extern gid_t old_gid; +/* Memory allocation in flight. Each thread can have a limited number + of allocation in flight. No need to create dynamic data + structures. We use fixed indices. */ +enum in_flight + { + IDX_result_data = 0, + /* Keep the IDX_record_data entry last at all times. */ + IDX_record_data = 1, + IDX_last + }; +extern __thread struct mem_in_flight +{ + struct + { + int dbidx; + nscd_ssize_t blocklen; + void *blockaddr; + } block[IDX_last]; + + struct mem_in_flight *next; +} mem_in_flight; +/* Global list of the mem_in_flight variables of all the threads. */ +extern struct mem_in_flight *mem_in_flight_list; + + /* Prototypes for global functions. */ /* nscd.c */ @@ -271,7 +296,8 @@ struct datahead *dh); /* mem.c */ -extern void *mempool_alloc (struct database_dyn *db, size_t len); +extern void *mempool_alloc (struct database_dyn *db, size_t len, + enum in_flight idx); extern void gc (struct database_dyn *db); =================================================================== RCS file: /cvs/glibc/libc/nscd/mem.c,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- libc/nscd/mem.c 2007/11/25 21:07:14 1.12 +++ libc/nscd/mem.c 2008/04/19 16:41:32 1.13 @@ -1,5 +1,5 @@ /* Cache memory handling. - Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2004. @@ -197,6 +197,31 @@ } assert (cnt == db->head->nentries); + /* Go through the list of in-flight memory blocks. */ + struct mem_in_flight *mrunp = mem_in_flight_list; + while (mrunp != NULL) + { + /* NB: There can be no race between this test and another thread + setting the field to the index we are looking for because + this would require the other thread to also have the memlock + for the database. + + NB2: we do not have to look at latter blocks (higher indices) if + earlier blocks are not in flight. They are always allocated in + sequence. */ + for (enum in_flight idx = IDX_result_data; + idx < IDX_last && mrunp->block[idx].dbidx == db - dbs; ++idx) + { + assert ((char *) mrunp->block[idx].blockaddr > db->data); + assert ((char *) mrunp->block[idx].blockaddr + + mrunp->block[0].blocklen <= db->data + db->memsize); + markrange (mark, (char *) mrunp->block[idx].blockaddr - db->data, + mrunp->block[idx].blocklen); + } + + mrunp = mrunp->next; + } + /* Sort the entries by the addresses of the referenced data. All the entries pointing to the same DATAHEAD object will have the same key. Stability of the sorting is unimportant. */ @@ -503,7 +528,7 @@ void * -mempool_alloc (struct database_dyn *db, size_t len) +mempool_alloc (struct database_dyn *db, size_t len, enum in_flight idx) { /* Make sure LEN is a multiple of our maximum alignment so we can keep track of used memory is multiples of this alignment value. */ @@ -567,6 +592,12 @@ db->head->first_free += len; db->last_alloc_failed = false; + + /* Remember that we have allocated this memory. */ + assert (idx >= 0 && idx < IDX_last); + mem_in_flight.block[idx].dbidx = db - dbs; + mem_in_flight.block[idx].blocklen = len; + mem_in_flight.block[idx].blockaddr = res; } pthread_mutex_unlock (&db->memlock); =================================================================== RCS file: /cvs/glibc/libc/nscd/cache.c,v retrieving revision 1.35 retrieving revision 1.36 diff -u -r1.35 -r1.36 --- libc/nscd/cache.c 2007/11/25 21:47:35 1.35 +++ libc/nscd/cache.c 2008/04/19 16:41:46 1.36 @@ -1,4 +1,4 @@ -/* Copyright (c) 1998, 1999, 2003-2006, 2007 Free Software Foundation, Inc. +/* Copyright (c) 1998, 1999, 2003-2007, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. @@ -155,11 +155,16 @@ unsigned long int hash = __nis_hash (key, len) % table->head->module; struct hashentry *newp; - newp = mempool_alloc (table, sizeof (struct hashentry)); + newp = mempool_alloc (table, sizeof (struct hashentry), IDX_record_data); /* If we cannot allocate memory, just do not do anything. */ if (newp == NULL) { ++table->head->addfailed; + + /* Mark the in-flight memory as unused. */ + for (enum in_flight idx = 0; idx < IDX_record_data; ++idx) + mem_in_flight.block[idx].dbidx = -1; + return -1; } @@ -215,6 +220,10 @@ else next_wakeup = table->wakeup_time; + /* Mark the in-flight memory as unused. */ + for (enum in_flight idx = 0; idx < IDX_last; ++idx) + mem_in_flight.block[idx].dbidx = -1; + return 0; } =================================================================== RCS file: /cvs/glibc/libc/nscd/connections.c,v retrieving revision 1.109 retrieving revision 1.110 diff -u -r1.109 -r1.110 --- libc/nscd/connections.c 2008/03/04 01:53:50 1.109 +++ libc/nscd/connections.c 2008/04/19 16:42:02 1.110 @@ -225,6 +225,11 @@ /* Number of times clients had to wait. */ unsigned long int client_queued; +/* Data structure for recording in-flight memory allocation. */ +__thread struct mem_in_flight mem_in_flight; +/* Global list of the mem_in_flight variables of all the threads. */ +struct mem_in_flight *mem_in_flight_list; + ssize_t writeall (int fd, const void *buf, size_t len) @@ -964,7 +969,7 @@ /* Handle new request. */ static void -handle_request (int fd, request_header *req, void *key, uid_t uid) +handle_request (int fd, request_header *req, void *key, uid_t uid, pid_t pid) { if (__builtin_expect (req->version, NSCD_VERSION) != NSCD_VERSION) { @@ -979,7 +984,31 @@ if (selinux_enabled && nscd_request_avc_has_perm (fd, req->type) != 0) { if (debug_level > 0) - dbg_log (_("request not handled due to missing permission")); + { +#ifdef SO_PEERCRED +# ifdef PATH_MAX + char buf[PATH_MAX]; +# else + char buf[4096]; +# endif + + snprintf (buf, sizeof (buf), "/proc/%ld/exe", (long int) pid); + ssize_t n = readlink (buf, buf, sizeof (buf) - 1); + + if (n <= 0) + dbg_log (_("\ +request from %ld not handled due to missing permission"), (long int) pid); + else + { + buf[n] = '\0'; + dbg_log (_("\ +request from '%s' [%ld] not handled due to missing permission"), + buf, (long int) pid); + } +#else + dbg_log (_("request not handled due to missing permission")); +#endif + } return; } @@ -1426,6 +1455,16 @@ { char buf[256]; + /* Initialize the memory-in-flight list. */ + for (enum in_flight idx = 0; idx < IDX_last; ++idx) + mem_in_flight.block[idx].dbidx = -1; + /* And queue this threads structure. */ + do + mem_in_flight.next = mem_in_flight_list; + while (atomic_compare_and_exchange_bool_acq (&mem_in_flight_list, + &mem_in_flight, + mem_in_flight.next) != 0); + /* Initial locking. */ pthread_mutex_lock (&readylist_lock); @@ -1491,6 +1530,8 @@ if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) == 0) pid = caller.pid; } +#else + const pid_t pid = 0; #endif /* It should not be possible to crash the nscd with a silly @@ -1531,7 +1572,7 @@ } /* Phew, we got all the data, now process it. */ - handle_request (fd, &req, keybuf, uid); + handle_request (fd, &req, keybuf, uid, pid); } close_and_out: =================================================================== RCS file: /cvs/glibc/libc/nscd/servicescache.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- libc/nscd/servicescache.c 2007/11/25 21:26:37 1.5 +++ libc/nscd/servicescache.c 2008/04/19 16:42:32 1.6 @@ -1,5 +1,5 @@ /* Cache handling for services lookup. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@drepper.com>, 2007. @@ -103,7 +103,8 @@ written = TEMP_FAILURE_RETRY (send (fd, ¬found, total, MSG_NOSIGNAL)); - dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len); + dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, + IDX_result_data); /* If we cannot permanently store the result, so be it. */ if (dataset != NULL) { @@ -190,7 +191,8 @@ if (he == NULL) { dataset = (struct dataset *) mempool_alloc (db, - total + req->key_len); + total + req->key_len, + IDX_result_data); if (dataset == NULL) ++db->head->addfailed; } @@ -261,7 +263,8 @@ /* We have to create a new record. Just allocate appropriate memory and copy it. */ struct dataset *newp - = (struct dataset *) mempool_alloc (db, total + req->key_len); + = (struct dataset *) mempool_alloc (db, total + req->key_len, + IDX_result_data); if (newp != NULL) { /* Adjust pointers into the memory block. */ =================================================================== RCS file: /cvs/glibc/libc/nscd/pwdcache.c,v retrieving revision 1.48 retrieving revision 1.49 diff -u -r1.48 -r1.49 --- libc/nscd/pwdcache.c 2007/11/25 21:27:50 1.48 +++ libc/nscd/pwdcache.c 2008/04/19 16:42:32 1.49 @@ -1,5 +1,5 @@ /* Cache handling for passwd lookup. - Copyright (C) 1998-2005, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 1998-2005, 2006, 2007, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. @@ -120,7 +120,8 @@ written = TEMP_FAILURE_RETRY (send (fd, ¬found, total, MSG_NOSIGNAL)); - dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len); + dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, + IDX_result_data); /* If we cannot permanently store the result, so be it. */ if (dataset != NULL) { @@ -199,7 +200,8 @@ if (he == NULL) { - dataset = (struct dataset *) mempool_alloc (db, total + n); + dataset = (struct dataset *) mempool_alloc (db, total + n, + IDX_result_data); if (dataset == NULL) ++db->head->addfailed; } @@ -270,7 +272,8 @@ /* We have to create a new record. Just allocate appropriate memory and copy it. */ struct dataset *newp - = (struct dataset *) mempool_alloc (db, total + n); + = (struct dataset *) mempool_alloc (db, total + n, + IDX_result_data); if (newp != NULL) { /* Adjust pointer into the memory block. */ =================================================================== RCS file: /cvs/glibc/libc/nscd/initgrcache.c,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- libc/nscd/initgrcache.c 2007/11/25 21:29:04 1.12 +++ libc/nscd/initgrcache.c 2008/04/19 16:42:32 1.13 @@ -1,5 +1,5 @@ /* Cache handling for host lookup. - Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2004. @@ -197,7 +197,8 @@ written = TEMP_FAILURE_RETRY (send (fd, ¬found, total, MSG_NOSIGNAL)); - dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len); + dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, + IDX_result_data); /* If we cannot permanently store the result, so be it. */ if (dataset != NULL) { @@ -259,7 +260,8 @@ if (he == NULL) { dataset = (struct dataset *) mempool_alloc (db, - total + req->key_len); + total + req->key_len, + IDX_result_data); if (dataset == NULL) ++db->head->addfailed; } @@ -329,7 +331,8 @@ /* We have to create a new record. Just allocate appropriate memory and copy it. */ struct dataset *newp - = (struct dataset *) mempool_alloc (db, total + req->key_len); + = (struct dataset *) mempool_alloc (db, total + req->key_len, + IDX_result_data); if (newp != NULL) { /* Adjust pointer into the memory block. */ =================================================================== RCS file: /cvs/glibc/libc/nscd/hstcache.c,v retrieving revision 1.46 retrieving revision 1.47 diff -u -r1.46 -r1.47 --- libc/nscd/hstcache.c 2007/11/25 21:24:14 1.46 +++ libc/nscd/hstcache.c 2008/04/19 16:42:32 1.47 @@ -1,5 +1,5 @@ /* Cache handling for host lookup. - Copyright (C) 1998-2005, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 1998-2005, 2006, 2007, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. @@ -121,7 +121,8 @@ written = TEMP_FAILURE_RETRY (send (fd, ¬found, total, MSG_NOSIGNAL)); - dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len); + dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, + IDX_result_data); /* If we cannot permanently store the result, so be it. */ if (dataset != NULL) { @@ -226,7 +227,8 @@ if (he == NULL && h_addr_list_cnt == 1) { dataset = (struct dataset *) mempool_alloc (db, - total + req->key_len); + total + req->key_len, + IDX_result_data); if (dataset == NULL) ++db->head->addfailed; } @@ -312,7 +314,8 @@ appropriate memory and copy it. */ struct dataset *newp = (struct dataset *) mempool_alloc (db, - total + req->key_len); + total + req->key_len, + IDX_result_data); if (newp != NULL) { /* Adjust pointers into the memory block. */ =================================================================== RCS file: /cvs/glibc/libc/nscd/grpcache.c,v retrieving revision 1.50 retrieving revision 1.51 diff -u -r1.50 -r1.51 --- libc/nscd/grpcache.c 2007/11/25 21:25:22 1.50 +++ libc/nscd/grpcache.c 2008/04/19 16:42:32 1.51 @@ -1,5 +1,5 @@ /* Cache handling for group lookup. - Copyright (C) 1998-2005, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 1998-2005, 2006, 2007, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. @@ -113,7 +113,8 @@ written = TEMP_FAILURE_RETRY (send (fd, ¬found, total, MSG_NOSIGNAL)); - dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len); + dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, + IDX_result_data); /* If we cannot permanently store the result, so be it. */ if (dataset != NULL) { @@ -204,7 +205,8 @@ if (he == NULL) { - dataset = (struct dataset *) mempool_alloc (db, total + n); + dataset = (struct dataset *) mempool_alloc (db, total + n, + IDX_result_data); if (dataset == NULL) ++db->head->addfailed; } @@ -274,7 +276,8 @@ /* We have to create a new record. Just allocate appropriate memory and copy it. */ struct dataset *newp - = (struct dataset *) mempool_alloc (db, total + n); + = (struct dataset *) mempool_alloc (db, total + n, + IDX_result_data); if (newp != NULL) { /* Adjust pointers into the memory block. */ =================================================================== RCS file: /cvs/glibc/libc/nscd/aicache.c,v retrieving revision 1.17 retrieving revision 1.18 diff -u -r1.17 -r1.18 --- libc/nscd/aicache.c 2007/11/25 12:56:35 1.17 +++ libc/nscd/aicache.c 2008/04/19 16:42:32 1.18 @@ -1,5 +1,5 @@ /* Cache handling for host lookup. - Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2004. @@ -262,7 +262,8 @@ { dataset = (struct dataset *) mempool_alloc (db, total - + req->key_len); + + req->key_len, + IDX_result_data); if (dataset == NULL) ++db->head->addfailed; } @@ -338,7 +339,8 @@ struct dataset *newp = (struct dataset *) mempool_alloc (db, total - + req->key_len); + + req->key_len, + IDX_result_data); if (__builtin_expect (newp != NULL, 1)) { /* Adjust pointer into the memory block. */ @@ -424,7 +426,8 @@ if (fd != -1) TEMP_FAILURE_RETRY (send (fd, ¬found, total, MSG_NOSIGNAL)); - dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len); + dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, + IDX_result_data); /* If we cannot permanently store the result, so be it. */ if (dataset != NULL) { =================================================================== RCS file: /cvs/glibc/libc/nscd/Makefile,v retrieving revision 1.55 retrieving revision 1.56 diff -u -r1.55 -r1.56 --- libc/nscd/Makefile 2008/04/19 16:40:58 1.55 +++ libc/nscd/Makefile 2008/04/22 15:53:11 1.56 @@ -90,8 +90,7 @@ nscd-cflags = -DIS_IN_nscd=1 -D_FORTIFY_SOURCE=2 ifeq (yesyes,$(have-fpie)$(build-shared)) -#nscd-cflags += -fpie -nscd-cflags += -fpic +nscd-cflags += -fpie endif ifeq (yes,$(have-ssp)) nscd-cflags += -fstack-protector =================================================================== RCS file: /cvs/glibc/libc/nscd/nscd.h,v retrieving revision 1.34 retrieving revision 1.35 diff -u -r1.34 -r1.35 --- libc/nscd/nscd.h 2008/04/19 16:41:20 1.34 +++ libc/nscd/nscd.h 2008/04/22 15:53:29 1.35 @@ -130,7 +130,7 @@ /* Global variables. */ -extern struct database_dyn dbs[lastdb]; +extern struct database_dyn dbs[lastdb] attribute_hidden; extern const char *const dbnames[lastdb]; extern const char *const serv2str[LASTREQ]; @@ -201,7 +201,7 @@ } block[IDX_last]; struct mem_in_flight *next; -} mem_in_flight; +} mem_in_flight attribute_tls_model_ie; /* Global list of the mem_in_flight variables of all the threads. */ extern struct mem_in_flight *mem_in_flight_list; =================================================================== RCS file: /cvs/glibc/libc/nscd/connections.c,v retrieving revision 1.110 retrieving revision 1.111 diff -u -r1.110 -r1.111 --- libc/nscd/connections.c 2008/04/19 16:42:02 1.110 +++ libc/nscd/connections.c 2008/04/22 15:53:45 1.111 @@ -226,7 +226,7 @@ unsigned long int client_queued; /* Data structure for recording in-flight memory allocation. */ -__thread struct mem_in_flight mem_in_flight; +__thread struct mem_in_flight mem_in_flight attribute_tls_model_ie; /* Global list of the mem_in_flight variables of all the threads. */ struct mem_in_flight *mem_in_flight_list; =================================================================== RCS file: /cvs/glibc/libc/nscd/cache.c,v retrieving revision 1.36 retrieving revision 1.37 diff -u -r1.36 -r1.37 --- libc/nscd/cache.c 2008/04/19 16:41:46 1.36 +++ libc/nscd/cache.c 2008/05/11 03:02:25 1.37 @@ -161,6 +161,11 @@ { ++table->head->addfailed; + /* If necessary mark the entry as unusable so that lookups will + not use it. */ + if (first) + packet->usable = false; + /* Mark the in-flight memory as unused. */ for (enum in_flight idx = 0; idx < IDX_record_data; ++idx) mem_in_flight.block[idx].dbidx = -1; =================================================================== RCS file: /cvs/glibc/libc/nscd/servicescache.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- libc/nscd/servicescache.c 2008/04/19 16:42:32 1.6 +++ libc/nscd/servicescache.c 2008/05/11 03:02:54 1.7 @@ -136,10 +136,8 @@ /* Now get the lock to safely insert the records. */ pthread_rwlock_rdlock (&db->lock); - if (cache_add (req->type, &dataset->strdata, req->key_len, - &dataset->head, true, db, owner) < 0) - /* Ensure the data can be recovered. */ - dataset->head.usable = false; + (void) cache_add (req->type, &dataset->strdata, req->key_len, + &dataset->head, true, db, owner); pthread_rwlock_unlock (&db->lock); @@ -332,11 +330,8 @@ /* Now get the lock to safely insert the records. */ pthread_rwlock_rdlock (&db->lock); - if (cache_add (req->type, key_copy, req->key_len, - &dataset->head, true, db, owner) < 0) - /* Could not allocate memory. Make sure the - data gets discarded. */ - dataset->head.usable = false; + (void) cache_add (req->type, key_copy, req->key_len, + &dataset->head, true, db, owner); pthread_rwlock_unlock (&db->lock); } =================================================================== RCS file: /cvs/glibc/libc/nscd/pwdcache.c,v retrieving revision 1.49 retrieving revision 1.50 diff -u -r1.49 -r1.50 --- libc/nscd/pwdcache.c 2008/04/19 16:42:32 1.49 +++ libc/nscd/pwdcache.c 2008/05/11 03:02:54 1.50 @@ -153,11 +153,8 @@ /* Now get the lock to safely insert the records. */ pthread_rwlock_rdlock (&db->lock); - if (cache_add (req->type, key_copy, req->key_len, - &dataset->head, true, db, owner) < 0) - /* Ensure the data can be recovered. */ - dataset->head.usable = false; - + (void) cache_add (req->type, key_copy, req->key_len, + &dataset->head, true, db, owner); pthread_rwlock_unlock (&db->lock); @@ -352,12 +349,7 @@ { if (cache_add (GETPWBYUID, cp, key_offset, &dataset->head, true, db, owner) < 0) - { - /* Could not allocate memory. Make sure the data gets - discarded. */ - dataset->head.usable = false; - goto out; - } + goto out; first = false; } @@ -366,12 +358,7 @@ { if (cache_add (GETPWBYNAME, key_copy, key_len + 1, &dataset->head, true, db, owner) < 0) - { - /* Could not allocate memory. Make sure the data gets - discarded. */ - dataset->head.usable = false; - goto out; - } + goto out; first = false; } @@ -384,12 +371,8 @@ { if (req->type == GETPWBYNAME && db->propagate) (void) cache_add (GETPWBYUID, cp, key_offset, &dataset->head, - req->type != GETPWBYNAME, db, owner); + false, db, owner); } - else if (first) - /* Could not allocate memory. Make sure the data gets - discarded. */ - dataset->head.usable = false; out: pthread_rwlock_unlock (&db->lock); =================================================================== RCS file: /cvs/glibc/libc/nscd/initgrcache.c,v retrieving revision 1.13 retrieving revision 1.14 diff -u -r1.13 -r1.14 --- libc/nscd/initgrcache.c 2008/04/19 16:42:32 1.13 +++ libc/nscd/initgrcache.c 2008/05/11 03:02:54 1.14 @@ -230,10 +230,8 @@ /* Now get the lock to safely insert the records. */ pthread_rwlock_rdlock (&db->lock); - if (cache_add (req->type, key_copy, req->key_len, - &dataset->head, true, db, uid) < 0) - /* Ensure the data can be recovered. */ - dataset->head.usable = false; + (void) cache_add (req->type, key_copy, req->key_len, + &dataset->head, true, db, uid); pthread_rwlock_unlock (&db->lock); @@ -399,11 +397,8 @@ /* Now get the lock to safely insert the records. */ pthread_rwlock_rdlock (&db->lock); - if (cache_add (INITGROUPS, cp, req->key_len, &dataset->head, true, - db, uid) < 0) - /* Could not allocate memory. Make sure the data gets - discarded. */ - dataset->head.usable = false; + (void) cache_add (INITGROUPS, cp, req->key_len, &dataset->head, true, + db, uid); pthread_rwlock_unlock (&db->lock); } =================================================================== RCS file: /cvs/glibc/libc/nscd/hstcache.c,v retrieving revision 1.47 retrieving revision 1.48 diff -u -r1.47 -r1.48 --- libc/nscd/hstcache.c 2008/04/19 16:42:32 1.47 +++ libc/nscd/hstcache.c 2008/05/11 03:02:54 1.48 @@ -155,10 +155,8 @@ /* Now get the lock to safely insert the records. */ pthread_rwlock_rdlock (&db->lock); - if (cache_add (req->type, &dataset->strdata, req->key_len, - &dataset->head, true, db, owner) < 0) - /* Ensure the data can be recovered. */ - dataset->head.usable = false; + (void) cache_add (req->type, &dataset->strdata, req->key_len, + &dataset->head, true, db, owner); pthread_rwlock_unlock (&db->lock); @@ -409,11 +407,8 @@ || req->type == GETHOSTBYADDR || req->type == GETHOSTBYADDRv6); - if (cache_add (req->type, key_copy, req->key_len, - &dataset->head, true, db, owner) < 0) - /* Could not allocate memory. Make sure the - data gets discarded. */ - dataset->head.usable = false; + (void) cache_add (req->type, key_copy, req->key_len, + &dataset->head, true, db, owner); pthread_rwlock_unlock (&db->lock); } =================================================================== RCS file: /cvs/glibc/libc/nscd/grpcache.c,v retrieving revision 1.51 retrieving revision 1.52 diff -u -r1.51 -r1.52 --- libc/nscd/grpcache.c 2008/04/19 16:42:32 1.51 +++ libc/nscd/grpcache.c 2008/05/11 03:02:54 1.52 @@ -146,10 +146,8 @@ /* Now get the lock to safely insert the records. */ pthread_rwlock_rdlock (&db->lock); - if (cache_add (req->type, &dataset->strdata, req->key_len, - &dataset->head, true, db, owner) < 0) - /* Ensure the data can be recovered. */ - dataset->head.usable = false; + (void) cache_add (req->type, &dataset->strdata, req->key_len, + &dataset->head, true, db, owner); pthread_rwlock_unlock (&db->lock); @@ -356,12 +354,7 @@ { if (cache_add (GETGRBYGID, cp, key_offset, &dataset->head, true, db, owner) < 0) - { - /* Could not allocate memory. Make sure the data gets - discarded. */ - dataset->head.usable = false; - goto out; - } + goto out; first = false; } @@ -370,12 +363,7 @@ { if (cache_add (GETGRBYNAME, key_copy, key_len + 1, &dataset->head, true, db, owner) < 0) - { - /* Could not allocate memory. Make sure the data gets - discarded. */ - dataset->head.usable = false; - goto out; - } + goto out; first = false; } @@ -389,12 +377,8 @@ { if (req->type == GETGRBYNAME && db->propagate) (void) cache_add (GETGRBYGID, cp, key_offset, &dataset->head, - req->type != GETGRBYNAME, db, owner); + false, db, owner); } - else if (first) - /* Could not allocate memory. Make sure the data gets - discarded. */ - dataset->head.usable = false; out: pthread_rwlock_unlock (&db->lock); =================================================================== RCS file: /cvs/glibc/libc/nscd/aicache.c,v retrieving revision 1.19 retrieving revision 1.20 diff -u -r1.19 -r1.20 --- libc/nscd/aicache.c 2008/05/10 23:23:52 1.19 +++ libc/nscd/aicache.c 2008/05/11 03:02:54 1.20 @@ -556,10 +556,8 @@ /* Now get the lock to safely insert the records. */ pthread_rwlock_rdlock (&db->lock); - if (cache_add (req->type, key_copy, req->key_len, &dataset->head, true, - db, uid) < 0) - /* Ensure the data can be recovered. */ - dataset->head.usable = false; + (void) cache_add (req->type, key_copy, req->key_len, &dataset->head, + true, db, uid); pthread_rwlock_unlock (&db->lock); =================================================================== RCS file: /cvs/glibc/libc/nscd/mem.c,v retrieving revision 1.13 retrieving revision 1.14 diff -u -r1.13 -r1.14 --- libc/nscd/mem.c 2008/04/19 16:41:32 1.13 +++ libc/nscd/mem.c 2008/05/18 02:45:37 1.14 @@ -132,12 +132,12 @@ stack_used = 0; size_t memory_needed = ((db->head->first_free / BLOCK_ALIGN + BITS - 1) / BITS) * sizeof (BITMAP_T); - if (memory_needed <= MAX_STACK_USE) + if (stack_used + memory_needed <= MAX_STACK_USE) { mark = (BITMAP_T *) alloca (memory_needed); mark_use_malloc = false; memset (mark, '\0', memory_needed); - stack_used = memory_needed; + stack_used += memory_needed; } else { =================================================================== RCS file: /cvs/glibc/libc/nscd/nscd.h,v retrieving revision 1.35 retrieving revision 1.36 diff -u -r1.35 -r1.36 --- libc/nscd/nscd.h 2008/04/22 15:53:29 1.35 +++ libc/nscd/nscd.h 2008/05/18 03:55:50 1.36 @@ -197,7 +197,7 @@ { int dbidx; nscd_ssize_t blocklen; - void *blockaddr; + nscd_ssize_t blockoff; } block[IDX_last]; struct mem_in_flight *next; =================================================================== RCS file: /cvs/glibc/libc/nscd/mem.c,v retrieving revision 1.14 retrieving revision 1.15 diff -u -r1.14 -r1.15 --- libc/nscd/mem.c 2008/05/18 02:45:37 1.14 +++ libc/nscd/mem.c 2008/05/18 03:57:06 1.15 @@ -212,11 +212,12 @@ for (enum in_flight idx = IDX_result_data; idx < IDX_last && mrunp->block[idx].dbidx == db - dbs; ++idx) { - assert ((char *) mrunp->block[idx].blockaddr > db->data); - assert ((char *) mrunp->block[idx].blockaddr - + mrunp->block[0].blocklen <= db->data + db->memsize); - markrange (mark, (char *) mrunp->block[idx].blockaddr - db->data, - mrunp->block[idx].blocklen); + assert (mrunp->block[idx].blockoff >= 0); + assert (mrunp->block[idx].blocklen < db->memsize); + assert (mrunp->block[idx].blockoff + + mrunp->block[0].blocklen <= db->memsize); + markrange (mark, mrunp->block[idx].blockoff, + mrunp->block[idx].blocklen); } mrunp = mrunp->next; @@ -589,15 +590,16 @@ } else { - db->head->first_free += len; - - db->last_alloc_failed = false; - /* Remember that we have allocated this memory. */ assert (idx >= 0 && idx < IDX_last); mem_in_flight.block[idx].dbidx = db - dbs; mem_in_flight.block[idx].blocklen = len; - mem_in_flight.block[idx].blockaddr = res; + mem_in_flight.block[idx].blockoff = db->head->first_free; + + db->head->first_free += len; + + db->last_alloc_failed = false; + } pthread_mutex_unlock (&db->memlock); =================================================================== RCS file: /cvs/glibc/libc/nscd/mem.c,v retrieving revision 1.15 retrieving revision 1.16 diff -u -r1.15 -r1.16 --- libc/nscd/mem.c 2008/05/18 03:57:06 1.15 +++ libc/nscd/mem.c 2008/05/18 04:16:23 1.16 @@ -79,6 +79,7 @@ markrange (BITMAP_T *mark, ref_t start, size_t len) { /* Adjust parameters for block alignment. */ + assert ((start & BLOCK_ALIGN_M1) == 0); start /= BLOCK_ALIGN; len = (len + BLOCK_ALIGN_M1) / BLOCK_ALIGN; @@ -93,7 +94,7 @@ return; } - mark[elem++] |= 0xff << (start % BITS); + mark[elem++] |= ALLBITS << (start % BITS); len -= BITS - (start % BITS); } =================================================================== RCS file: /cvs/glibc/libc/nscd/mem.c,v retrieving revision 1.16 retrieving revision 1.17 diff -u -r1.16 -r1.17 --- libc/nscd/mem.c 2008/05/18 04:16:23 1.16 +++ libc/nscd/mem.c 2008/05/18 04:25:36 1.17 @@ -131,8 +131,8 @@ size_t stack_used = sizeof (bool) * db->head->module; if (__builtin_expect (stack_used > MAX_STACK_USE, 0)) stack_used = 0; - size_t memory_needed = ((db->head->first_free / BLOCK_ALIGN + BITS - 1) - / BITS) * sizeof (BITMAP_T); + size_t nmark = (db->head->first_free / BLOCK_ALIGN + BITS - 1) / BITS; + size_t memory_needed = nmark * sizeof (BITMAP_T); if (stack_used + memory_needed <= MAX_STACK_USE) { mark = (BITMAP_T *) alloca (memory_needed); @@ -234,7 +234,7 @@ qsort (he, cnt, sizeof (struct hashentry *), sort_he); /* Determine the highest used address. */ - size_t high = sizeof (mark); + size_t high = nmark; while (high > 0 && mark[high - 1] == 0) --high; =================================================================== RCS file: /cvs/glibc/libc/nscd/mem.c,v retrieving revision 1.17 retrieving revision 1.18 diff -u -r1.17 -r1.18 --- libc/nscd/mem.c 2008/05/18 04:25:36 1.17 +++ libc/nscd/mem.c 2008/05/18 06:28:54 1.18 @@ -24,6 +24,7 @@ #include <inttypes.h> #include <libintl.h> #include <limits.h> +#include <obstack.h> #include <stdlib.h> #include <string.h> #include <unistd.h> @@ -157,6 +158,7 @@ he = alloca (db->head->nentries * sizeof (struct hashentry *)); he_data = alloca (db->head->nentries * sizeof (struct hashentry *)); he_use_malloc = false; + stack_used += memory_needed; } else { @@ -305,6 +307,10 @@ size_t size; struct moveinfo *next; } *moves = NULL; +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free + struct obstack ob; + obstack_init (&ob); while (byte < high) { @@ -365,8 +371,14 @@ displacement. */ ref_t disp = off_alloc - off_free; - struct moveinfo *new_move - = (struct moveinfo *) alloca (sizeof (*new_move)); + struct moveinfo *new_move; + if (stack_used + sizeof (*new_move) <= MAX_STACK_USE) + { + new_move = alloca (sizeof (*new_move)); + stack_used += sizeof (*new_move); + } + else + new_move = obstack_alloc (&ob, sizeof (*new_move)); new_move->from = db->data + off_alloc; new_move->to = db->data + off_free; new_move->size = off_allocend - off_alloc; @@ -526,6 +538,8 @@ free (he); if (mark_use_malloc) free (mark); + + obstack_free (&ob, NULL); } =================================================================== RCS file: /cvs/glibc/libc/nscd/cache.c,v retrieving revision 1.37 retrieving revision 1.38 diff -u -r1.37 -r1.38 --- libc/nscd/cache.c 2008/05/11 03:02:25 1.37 +++ libc/nscd/cache.c 2008/05/18 21:53:38 1.38 @@ -135,7 +135,7 @@ int cache_add (int type, const void *key, size_t len, struct datahead *packet, bool first, struct database_dyn *table, - uid_t owner) + uid_t owner, bool prune_wakeup) { if (__builtin_expect (debug_level >= 2, 0)) { @@ -180,6 +180,7 @@ assert (newp->key + newp->len <= table->head->first_free); newp->owner = owner; newp->packet = (char *) packet - table->data; + assert ((newp->packet & BLOCK_ALIGN_M1) == 0); /* Put the new entry in the first position. */ do @@ -211,19 +212,27 @@ (char *) &table->head->array[hash] - (char *) table->head + sizeof (ref_t), MS_ASYNC); - /* Perhaps the prune thread for the data is not running in a long - time. Wake it if necessary. */ - time_t next_wakeup = table->wakeup_time; - while (next_wakeup + CACHE_PRUNE_INTERVAL > packet->timeout) - if (atomic_compare_and_exchange_bool_acq (&table->wakeup_time, - packet->timeout, - next_wakeup) == 0) - { + /* We do not have to worry about the pruning thread if we are + re-adding the data since this is done by the pruning thread. We + also do not have to do anything in case this is not the first + time the data is entered since different data heads all have the + same timeout. */ + if (first && prune_wakeup) + { + /* Perhaps the prune thread for the table is not running in a long + time. Wake it if necessary. */ + pthread_mutex_lock (&table->prune_lock); + time_t next_wakeup = table->wakeup_time; + bool do_wakeup = false; + if (next_wakeup > packet->timeout + CACHE_PRUNE_INTERVAL) + { + table->wakeup_time = packet->timeout; + do_wakeup = true; + } + pthread_mutex_unlock (&table->prune_lock); + if (do_wakeup) pthread_cond_signal (&table->prune_cond); - break; - } - else - next_wakeup = table->wakeup_time; + } /* Mark the in-flight memory as unused. */ for (enum in_flight idx = 0; idx < IDX_last; ++idx) @@ -436,7 +445,8 @@ ref_t *old = &table->head->array[first]; ref_t run = table->head->array[first]; - while (run != ENDREF) + assert (run != ENDREF); + do { struct hashentry *runp = (struct hashentry *) (data + run); struct datahead *dh @@ -462,6 +472,7 @@ run = runp->next; } } + while (run != ENDREF); } ++first; =================================================================== RCS file: /cvs/glibc/libc/nscd/nscd.h,v retrieving revision 1.36 retrieving revision 1.37 diff -u -r1.36 -r1.37 --- libc/nscd/nscd.h 2008/05/18 03:55:50 1.36 +++ libc/nscd/nscd.h 2008/05/18 21:53:48 1.37 @@ -231,7 +231,8 @@ uid_t owner); extern int cache_add (int type, const void *key, size_t len, struct datahead *packet, bool first, - struct database_dyn *table, uid_t owner); + struct database_dyn *table, uid_t owner, + bool prune_wakeup); extern time_t prune_cache (struct database_dyn *table, time_t now, int fd); /* pwdcache.c */ =================================================================== RCS file: /cvs/glibc/libc/nscd/servicescache.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- libc/nscd/servicescache.c 2008/05/11 03:02:54 1.7 +++ libc/nscd/servicescache.c 2008/05/18 21:54:07 1.8 @@ -137,7 +137,7 @@ pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, &dataset->strdata, req->key_len, - &dataset->head, true, db, owner); + &dataset->head, true, db, owner, he == NULL); pthread_rwlock_unlock (&db->lock); @@ -331,7 +331,7 @@ pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, key_copy, req->key_len, - &dataset->head, true, db, owner); + &dataset->head, true, db, owner, he == NULL); pthread_rwlock_unlock (&db->lock); } =================================================================== RCS file: /cvs/glibc/libc/nscd/pwdcache.c,v retrieving revision 1.50 retrieving revision 1.51 diff -u -r1.50 -r1.51 --- libc/nscd/pwdcache.c 2008/05/11 03:02:54 1.50 +++ libc/nscd/pwdcache.c 2008/05/18 21:54:07 1.51 @@ -154,7 +154,7 @@ pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, key_copy, req->key_len, - &dataset->head, true, db, owner); + &dataset->head, true, db, owner, he == NULL); pthread_rwlock_unlock (&db->lock); @@ -348,7 +348,7 @@ if (req->type == GETPWBYUID) { if (cache_add (GETPWBYUID, cp, key_offset, &dataset->head, true, - db, owner) < 0) + db, owner, he == NULL) < 0) goto out; first = false; @@ -357,7 +357,7 @@ else if (strcmp (key_copy, dataset->strdata) != 0) { if (cache_add (GETPWBYNAME, key_copy, key_len + 1, - &dataset->head, true, db, owner) < 0) + &dataset->head, true, db, owner, he == NULL) < 0) goto out; first = false; @@ -367,11 +367,12 @@ if ((req->type == GETPWBYNAME || db->propagate) && __builtin_expect (cache_add (GETPWBYNAME, dataset->strdata, pw_name_len, &dataset->head, - first, db, owner) == 0, 1)) + first, db, owner, he == NULL) + == 0, 1)) { if (req->type == GETPWBYNAME && db->propagate) (void) cache_add (GETPWBYUID, cp, key_offset, &dataset->head, - false, db, owner); + false, db, owner, false); } out: =================================================================== RCS file: /cvs/glibc/libc/nscd/initgrcache.c,v retrieving revision 1.14 retrieving revision 1.15 diff -u -r1.14 -r1.15 --- libc/nscd/initgrcache.c 2008/05/11 03:02:54 1.14 +++ libc/nscd/initgrcache.c 2008/05/18 21:54:07 1.15 @@ -231,7 +231,7 @@ pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, key_copy, req->key_len, - &dataset->head, true, db, uid); + &dataset->head, true, db, uid, he == NULL); pthread_rwlock_unlock (&db->lock); @@ -398,7 +398,7 @@ pthread_rwlock_rdlock (&db->lock); (void) cache_add (INITGROUPS, cp, req->key_len, &dataset->head, true, - db, uid); + db, uid, he == NULL); pthread_rwlock_unlock (&db->lock); } =================================================================== RCS file: /cvs/glibc/libc/nscd/hstcache.c,v retrieving revision 1.48 retrieving revision 1.49 diff -u -r1.48 -r1.49 --- libc/nscd/hstcache.c 2008/05/11 03:02:54 1.48 +++ libc/nscd/hstcache.c 2008/05/18 21:54:07 1.49 @@ -156,7 +156,7 @@ pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, &dataset->strdata, req->key_len, - &dataset->head, true, db, owner); + &dataset->head, true, db, owner, he == NULL); pthread_rwlock_unlock (&db->lock); @@ -408,7 +408,7 @@ || req->type == GETHOSTBYADDRv6); (void) cache_add (req->type, key_copy, req->key_len, - &dataset->head, true, db, owner); + &dataset->head, true, db, owner, he == NULL); pthread_rwlock_unlock (&db->lock); } =================================================================== RCS file: /cvs/glibc/libc/nscd/grpcache.c,v retrieving revision 1.52 retrieving revision 1.53 diff -u -r1.52 -r1.53 --- libc/nscd/grpcache.c 2008/05/11 03:02:54 1.52 +++ libc/nscd/grpcache.c 2008/05/18 21:54:07 1.53 @@ -147,7 +147,7 @@ pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, &dataset->strdata, req->key_len, - &dataset->head, true, db, owner); + &dataset->head, true, db, owner, he == NULL); pthread_rwlock_unlock (&db->lock); @@ -353,7 +353,7 @@ if (req->type == GETGRBYGID) { if (cache_add (GETGRBYGID, cp, key_offset, &dataset->head, true, - db, owner) < 0) + db, owner, he == NULL) < 0) goto out; first = false; @@ -362,7 +362,7 @@ else if (strcmp (key_copy, gr_name) != 0) { if (cache_add (GETGRBYNAME, key_copy, key_len + 1, - &dataset->head, true, db, owner) < 0) + &dataset->head, true, db, owner, he == NULL) < 0) goto out; first = false; @@ -372,12 +372,13 @@ if ((req->type == GETGRBYNAME || db->propagate) && __builtin_expect (cache_add (GETGRBYNAME, gr_name, gr_name_len, - &dataset->head, first, db, owner) + &dataset->head, first, db, owner, + he == NULL) == 0, 1)) { if (req->type == GETGRBYNAME && db->propagate) (void) cache_add (GETGRBYGID, cp, key_offset, &dataset->head, - false, db, owner); + false, db, owner, false); } out: =================================================================== RCS file: /cvs/glibc/libc/nscd/aicache.c,v retrieving revision 1.21 retrieving revision 1.22 diff -u -r1.21 -r1.22 --- libc/nscd/aicache.c 2008/05/17 22:51:08 1.21 +++ libc/nscd/aicache.c 2008/05/18 21:54:07 1.22 @@ -558,7 +558,7 @@ pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, key_copy, req->key_len, &dataset->head, - true, db, uid); + true, db, uid, he == NULL); pthread_rwlock_unlock (&db->lock); =================================================================== RCS file: /cvs/glibc/libc/nscd/connections.c,v retrieving revision 1.111 retrieving revision 1.112 diff -u -r1.111 -r1.112 --- libc/nscd/connections.c 2008/04/22 15:53:45 1.111 +++ libc/nscd/connections.c 2008/05/18 21:54:26 1.112 @@ -1330,11 +1330,14 @@ } /* Synchronize memory. */ + int32_t certainly[lastdb]; for (int cnt = 0; cnt < lastdb; ++cnt) if (dbs[cnt].enabled) { /* Make sure nobody keeps using the database. */ dbs[cnt].head->timestamp = 0; + certainly[cnt] = dbs[cnt].head->nscd_certainly_running; + dbs[cnt].head->nscd_certainly_running = 0; if (dbs[cnt].persistent) // XXX async OK? @@ -1357,6 +1360,15 @@ dbg_log (_("cannot change current working directory to \"/\": %s"), strerror (errno)); paranoia = 0; + + /* Reenable the databases. */ + time_t now = time (NULL); + for (int cnt = 0; cnt < lastdb; ++cnt) + if (dbs[cnt].enabled) + { + dbs[cnt].head->timestamp = now; + dbs[cnt].head->nscd_certainly_running = certainly[cnt]; + } } @@ -1394,42 +1406,68 @@ int dont_need_update = setup_thread (&dbs[my_number]); + time_t now = time (NULL); + /* We are running. */ - dbs[my_number].head->timestamp = time (NULL); + dbs[my_number].head->timestamp = now; struct timespec prune_ts; - if (clock_gettime (timeout_clock, &prune_ts) == -1) + if (__builtin_expect (clock_gettime (timeout_clock, &prune_ts) == -1, 0)) /* Should never happen. */ abort (); /* Compute the initial timeout time. Prevent all the timers to go off at the same time by adding a db-based value. */ prune_ts.tv_sec += CACHE_PRUNE_INTERVAL + my_number; + dbs[my_number].wakeup_time = now + CACHE_PRUNE_INTERVAL + my_number; + + pthread_mutex_t *prune_lock = &dbs[my_number].prune_lock; + pthread_cond_t *prune_cond = &dbs[my_number].prune_cond; - pthread_mutex_lock (&dbs[my_number].prune_lock); + pthread_mutex_lock (prune_lock); while (1) { /* Wait, but not forever. */ - int e = pthread_cond_timedwait (&dbs[my_number].prune_cond, - &dbs[my_number].prune_lock, - &prune_ts); - assert (e == 0 || e == ETIMEDOUT); + int e = pthread_cond_timedwait (prune_cond, prune_lock, &prune_ts); + assert (__builtin_expect (e == 0 || e == ETIMEDOUT, 1)); time_t next_wait; - time_t now = time (NULL); + now = time (NULL); if (e == ETIMEDOUT || now >= dbs[my_number].wakeup_time) { + /* We will determine the new timout values based on the + cache content. Should there be concurrent additions to + the cache which are not accounted for in the cache + pruning we want to know about it. Therefore set the + timeout to the maximum. It will be descreased when adding + new entries to the cache, if necessary. */ + if (sizeof (time_t) == sizeof (long int)) + dbs[my_number].wakeup_time = LONG_MAX; + else + dbs[my_number].wakeup_time = INT_MAX; + + pthread_mutex_unlock (prune_lock); + next_wait = prune_cache (&dbs[my_number], now, -1); + next_wait = MAX (next_wait, CACHE_PRUNE_INTERVAL); /* If clients cannot determine for sure whether nscd is running we need to wake up occasionally to update the timestamp. Wait 90% of the update period. */ #define UPDATE_MAPPING_TIMEOUT (MAPPING_TIMEOUT * 9 / 10) if (__builtin_expect (! dont_need_update, 0)) - next_wait = MIN (UPDATE_MAPPING_TIMEOUT, next_wait); + { + next_wait = MIN (UPDATE_MAPPING_TIMEOUT, next_wait); + dbs[my_number].head->timestamp = now; + } + + pthread_mutex_lock (prune_lock); /* Make it known when we will wake up again. */ - dbs[my_number].wakeup_time = now + next_wait; + if (now + next_wait < dbs[my_number].wakeup_time) + dbs[my_number].wakeup_time = now + next_wait; + else + next_wait = dbs[my_number].wakeup_time - now; } else /* The cache was just pruned. Do not do it again now. Just =================================================================== RCS file: /cvs/glibc/libc/nscd/nscd_getserv_r.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- libc/nscd/nscd_getserv_r.c 2007/10/13 23:04:28 1.5 +++ libc/nscd/nscd_getserv_r.c 2008/06/03 10:22:52 1.6 @@ -53,7 +53,7 @@ portstr[sizeof (portstr) - 1] = '\0'; char *cp = _itoa_word (port, portstr + sizeof (portstr) - 1, 10, 0); - return nscd_getserv_r (portstr, portstr + sizeof (portstr) - cp, proto, + return nscd_getserv_r (cp, portstr + sizeof (portstr) - cp, proto, GETSERVBYPORT, result_buf, buf, buflen, result); } =================================================================== RCS file: /cvs/glibc/libc/nscd/hstcache.c,v retrieving revision 1.49 retrieving revision 1.50 diff -u -r1.49 -r1.50 --- libc/nscd/hstcache.c 2008/05/18 21:54:07 1.49 +++ libc/nscd/hstcache.c 2008/06/12 04:51:51 1.50 @@ -83,8 +83,7 @@ struct hashentry *he, struct datahead *dh, int errval, int32_t ttl) { - ssize_t total; - ssize_t written; + bool all_written = true; time_t t = time (NULL); /* We allocate all data in one memory block: the iov vector, @@ -108,18 +107,17 @@ if (reload_count != UINT_MAX) /* Do not reset the value if we never not reload the record. */ dh->nreloads = reload_count - 1; - - written = total = 0; } else { /* We have no data. This means we send the standard reply for this case. */ - written = total = sizeof (notfound); + ssize_t total = sizeof (notfound); - if (fd != -1) - written = TEMP_FAILURE_RETRY (send (fd, ¬found, total, - MSG_NOSIGNAL)); + if (fd != -1 && + TEMP_FAILURE_RETRY (send (fd, ¬found, total, + MSG_NOSIGNAL)) != total) + all_written = false; dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, IDX_result_data); @@ -181,6 +179,7 @@ char *key_copy = NULL; char *cp; size_t cnt; + ssize_t total; /* Determine the number of aliases. */ h_aliases_cnt = 0; @@ -208,7 +207,6 @@ + h_name_len + h_aliases_cnt * sizeof (uint32_t) + h_addr_list_cnt * hst->h_length); - written = total; /* If we refill the cache, first assume the reconrd did not change. Allocate memory on the cache since it is likely @@ -260,6 +258,9 @@ dataset->resp.h_addr_list_cnt = h_addr_list_cnt; dataset->resp.error = NETDB_SUCCESS; + /* Make sure there is no gap. */ + assert ((char *) (&dataset->resp.error + 1) == dataset->strdata); + cp = dataset->strdata; cp = mempcpy (cp, hst->h_name, h_name_len); @@ -286,6 +287,8 @@ we explicitly add the name here. */ key_copy = memcpy (cp, key, req->key_len); + assert ((char *) &dataset->resp + dataset->head.recsize == cp); + /* Now we can determine whether on refill we have to create a new record or not. */ if (he != NULL) @@ -351,20 +354,27 @@ <= (sizeof (struct database_pers_head) + db->head->module * sizeof (ref_t) + db->head->data_size)); - written = sendfileall (fd, db->wr_fd, - (char *) &dataset->resp - - (char *) db->head, total); + ssize_t written = sendfileall (fd, db->wr_fd, + (char *) &dataset->resp + - (char *) db->head, + dataset->head.recsize); + if (written != dataset->head.recsize) + { # ifndef __ASSUME_SENDFILE - if (written == -1 && errno == ENOSYS) - goto use_write; + if (written == -1 && errno == ENOSYS) + goto use_write; # endif + all_written = false; + } } else # ifndef __ASSUME_SENDFILE use_write: # endif #endif - written = writeall (fd, &dataset->resp, total); + if (writeall (fd, &dataset->resp, dataset->head.recsize) + != dataset->head.recsize) + all_written = false; } /* Add the record to the database. But only if it has not been @@ -414,7 +424,7 @@ } } - if (__builtin_expect (written != total, 0) && debug_level > 0) + if (__builtin_expect (!all_written, 0) && debug_level > 0) { char buf[256]; dbg_log (_("short write in %s: %s"), __FUNCTION__, =================================================================== RCS file: /cvs/glibc/libc/nscd/mem.c,v retrieving revision 1.18 retrieving revision 1.19 diff -u -r1.18 -r1.19 --- libc/nscd/mem.c 2008/05/18 06:28:54 1.18 +++ libc/nscd/mem.c 2008/06/12 04:52:27 1.19 @@ -235,6 +235,11 @@ /* Sort the entries by their address. */ qsort (he, cnt, sizeof (struct hashentry *), sort_he); +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free + struct obstack ob; + obstack_init (&ob); + /* Determine the highest used address. */ size_t high = nmark; while (high > 0 && mark[high - 1] == 0) @@ -307,10 +312,6 @@ size_t size; struct moveinfo *next; } *moves = NULL; -#define obstack_chunk_alloc xmalloc -#define obstack_chunk_free free - struct obstack ob; - obstack_init (&ob); while (byte < high) { =================================================================== RCS file: /cvs/glibc/libc/nscd/grpcache.c,v retrieving revision 1.53 retrieving revision 1.54 diff -u -r1.53 -r1.54 --- libc/nscd/grpcache.c 2008/05/18 21:54:07 1.53 +++ libc/nscd/grpcache.c 2008/06/12 16:03:36 1.54 @@ -190,7 +190,7 @@ gr_mem_len_total += gr_mem_len[gr_mem_cnt]; } - written = total = (sizeof (struct dataset) + written = total = (offsetof (struct dataset, strdata) + gr_mem_cnt * sizeof (uint32_t) + gr_name_len + gr_passwd_len + gr_mem_len_total); @@ -252,6 +252,9 @@ char *key_copy = cp + key_offset; assert (key_copy == (char *) rawmemchr (cp, '\0') + 1); + assert (cp == dataset->strdata + total - offsetof (struct dataset, + strdata)); + /* Now we can determine whether on refill we have to create a new record or not. */ if (he != NULL) =================================================================== RCS file: /cvs/glibc/libc/nscd/initgrcache.c,v retrieving revision 1.15 retrieving revision 1.16 diff -u -r1.15 -r1.16 --- libc/nscd/initgrcache.c 2008/05/18 21:54:07 1.15 +++ libc/nscd/initgrcache.c 2008/06/12 16:04:05 1.16 @@ -246,7 +246,8 @@ else { - written = total = sizeof (struct dataset) + start * sizeof (int32_t); + written = total = (offsetof (struct dataset, strdata) + + start * sizeof (int32_t)); /* If we refill the cache, first assume the reconrd did not change. Allocate memory on the cache since it is likely @@ -307,6 +308,9 @@ /* Finally the user name. */ memcpy (cp, key, req->key_len); + assert (cp == dataset->strdata + total - offsetof (struct dataset, + strdata)); + /* Now we can determine whether on refill we have to create a new record or not. */ if (he != NULL) =================================================================== RCS file: /cvs/glibc/libc/nscd/pwdcache.c,v retrieving revision 1.51 retrieving revision 1.52 diff -u -r1.51 -r1.52 --- libc/nscd/pwdcache.c 2008/05/18 21:54:07 1.51 +++ libc/nscd/pwdcache.c 2008/06/12 16:04:22 1.52 @@ -185,7 +185,8 @@ n = snprintf (buf, buf_len, "%d%c%n%s", pwd->pw_uid, '\0', &key_offset, (char *) key) + 1; - written = total = (sizeof (struct dataset) + pw_name_len + pw_passwd_len + written = total = (offsetof (struct dataset, strdata) + + pw_name_len + pw_passwd_len + pw_gecos_len + pw_dir_len + pw_shell_len); /* If we refill the cache, first assume the reconrd did not @@ -247,16 +248,28 @@ char *key_copy = cp + key_offset; assert (key_copy == (char *) rawmemchr (cp, '\0') + 1); + assert (cp == dataset->strdata + total - offsetof (struct dataset, + strdata)); + /* Now we can determine whether on refill we have to create a new record or not. */ if (he != NULL) { assert (fd == -1); - if (total + n == dh->allocsize - && total - offsetof (struct dataset, resp) == dh->recsize +#if 0 + if (dataset->head.datasize == dh->allocsize + && dataset->head.recsize == dh->recsize && memcmp (&dataset->resp, dh->data, dh->allocsize - offsetof (struct dataset, resp)) == 0) +#else + if (dataset->head.allocsize != dh->allocsize) + goto nnn; + if (dataset->head.recsize != dh->recsize) + goto nnn; + if(memcmp (&dataset->resp, dh->data, + dh->allocsize - offsetof (struct dataset, resp)) == 0) +#endif { /* The data has not changed. We will just bump the timeout value. Note that the new record has been @@ -266,6 +279,7 @@ } else { + nnn:; /* We have to create a new record. Just allocate appropriate memory and copy it. */ struct dataset *newp =================================================================== RCS file: /cvs/glibc/libc/nscd/servicescache.c,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- libc/nscd/servicescache.c 2008/05/18 21:54:07 1.8 +++ libc/nscd/servicescache.c 2008/06/12 16:04:37 1.9 @@ -173,7 +173,7 @@ total += s_aliases_len[cnt]; } - total += (sizeof (struct dataset) + total += (offsetof (struct dataset, strdata) + s_name_len + s_proto_len + s_aliases_cnt * sizeof (uint32_t));