summaryrefslogtreecommitdiff
path: root/nscd
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2006-05-31 15:10:35 +0000
committerJakub Jelinek <jakub@redhat.com>2006-05-31 15:10:35 +0000
commit2774ea772499f5779e846646824784a44377c69a (patch)
tree8c23b862c87c0056b7ef8296f527ca580d5e15a5 /nscd
parente482d83fb7eedcb449bfe80a6aa240cbd114c571 (diff)
Updated to fedora-glibc-20060531T1322cvs/fedora-glibc-2_4_90-11
Diffstat (limited to 'nscd')
-rw-r--r--nscd/cache.c37
-rw-r--r--nscd/connections.c29
-rw-r--r--nscd/nscd.c30
-rw-r--r--nscd/nscd.h3
4 files changed, 81 insertions, 18 deletions
diff --git a/nscd/cache.c b/nscd/cache.c
index 787f8b46f5..be9be2aa4f 100644
--- a/nscd/cache.c
+++ b/nscd/cache.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 1998, 1999, 2003, 2004, 2005 Free Software Foundation, Inc.
+/* Copyright (c) 1998, 1999, 2003-2005, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
@@ -190,13 +190,34 @@ cache_add (int type, const void *key, size_t len, struct datahead *packet,
free the data structures since some hash table entries share the same
data. */
void
-prune_cache (struct database_dyn *table, time_t now)
+prune_cache (struct database_dyn *table, time_t now, int fd)
{
size_t cnt = table->head->module;
/* If this table is not actually used don't do anything. */
if (cnt == 0)
- return;
+ {
+ if (fd != -1)
+ {
+ /* Reply to the INVALIDATE initiator. */
+ int32_t resp = 0;
+ writeall (fd, &resp, sizeof (resp));
+ }
+ return;
+ }
+
+ /* This function can be called from the cleanup thread but also in
+ response to an invalidate command. Make sure only one thread is
+ running. When not serving INVALIDATE request, no need for the
+ second to wait around. */
+ if (fd == -1)
+ {
+ if (pthread_mutex_trylock (&table->prunelock) != 0)
+ /* The work is already being done. */
+ return;
+ }
+ else
+ pthread_mutex_lock (&table->prunelock);
/* If we check for the modification of the underlying file we invalidate
the entries also in this case. */
@@ -367,6 +388,14 @@ prune_cache (struct database_dyn *table, time_t now)
}
while (cnt > 0);
+ if (fd != -1)
+ {
+ /* Reply to the INVALIDATE initiator that the cache has been
+ invalidated. */
+ int32_t resp = 0;
+ writeall (fd, &resp, sizeof (resp));
+ }
+
if (first <= last)
{
struct hashentry *head = NULL;
@@ -455,4 +484,6 @@ prune_cache (struct database_dyn *table, time_t now)
/* Run garbage collection if any entry has been removed or replaced. */
if (any)
gc (table);
+
+ pthread_mutex_unlock (&table->prunelock);
}
diff --git a/nscd/connections.c b/nscd/connections.c
index 8bd9a66be8..307337bffe 100644
--- a/nscd/connections.c
+++ b/nscd/connections.c
@@ -100,6 +100,7 @@ struct database_dyn dbs[lastdb] =
{
[pwddb] = {
.lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
+ .prunelock = PTHREAD_MUTEX_INITIALIZER,
.enabled = 0,
.check_file = 1,
.persistent = 0,
@@ -117,6 +118,7 @@ struct database_dyn dbs[lastdb] =
},
[grpdb] = {
.lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
+ .prunelock = PTHREAD_MUTEX_INITIALIZER,
.enabled = 0,
.check_file = 1,
.persistent = 0,
@@ -134,6 +136,7 @@ struct database_dyn dbs[lastdb] =
},
[hstdb] = {
.lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
+ .prunelock = PTHREAD_MUTEX_INITIALIZER,
.enabled = 0,
.check_file = 1,
.persistent = 0,
@@ -813,9 +816,10 @@ close_sockets (void)
static void
-invalidate_cache (char *key)
+invalidate_cache (char *key, int fd)
{
dbtype number;
+ int32_t resp;
if (strcmp (key, "passwd") == 0)
number = pwddb;
@@ -829,10 +833,19 @@ invalidate_cache (char *key)
res_init ();
}
else
- return;
+ {
+ resp = EINVAL;
+ writeall (fd, &resp, sizeof (resp));
+ return;
+ }
if (dbs[number].enabled)
- prune_cache (&dbs[number], LONG_MAX);
+ prune_cache (&dbs[number], LONG_MAX, fd);
+ else
+ {
+ resp = 0;
+ writeall (fd, &resp, sizeof (resp));
+ }
}
@@ -1089,7 +1102,7 @@ cannot handle old request version %d; current version is %d"),
else if (uid == 0)
{
if (req->type == INVALIDATE)
- invalidate_cache (key);
+ invalidate_cache (key, fd);
else
termination_handler (0);
}
@@ -1435,7 +1448,7 @@ handle_request: request received (Version = %d)"), req.version);
/* The pthread_cond_timedwait() call timed out. It is time
to clean up the cache. */
assert (my_number < lastdb);
- prune_cache (&dbs[my_number], time (NULL));
+ prune_cache (&dbs[my_number], time (NULL), -1);
if (clock_gettime (timeout_clock, &prune_ts) == -1)
/* Should never happen. */
@@ -1908,14 +1921,14 @@ sighup_handler (int signum)
{
/* Prune the password database. */
if (dbs[pwddb].enabled)
- prune_cache (&dbs[pwddb], LONG_MAX);
+ prune_cache (&dbs[pwddb], LONG_MAX, -1);
/* Prune the group database. */
if (dbs[grpdb].enabled)
- prune_cache (&dbs[grpdb], LONG_MAX);
+ prune_cache (&dbs[grpdb], LONG_MAX, -1);
/* Prune the host database. */
if (dbs[hstdb].enabled)
- prune_cache (&dbs[hstdb], LONG_MAX);
+ prune_cache (&dbs[hstdb], LONG_MAX, -1);
}
diff --git a/nscd/nscd.c b/nscd/nscd.c
index 917163af78..03359f3c05 100644
--- a/nscd/nscd.c
+++ b/nscd/nscd.c
@@ -336,9 +336,6 @@ parse_opt (int key, char *arg, struct argp_state *state)
exit (EXIT_FAILURE);
request_header req;
- ssize_t nbytes;
- struct iovec iov[2];
-
if (strcmp (arg, "passwd") == 0)
req.key_len = sizeof "passwd";
else if (strcmp (arg, "group") == 0)
@@ -351,17 +348,38 @@ parse_opt (int key, char *arg, struct argp_state *state)
req.version = NSCD_VERSION;
req.type = INVALIDATE;
+ struct iovec iov[2];
iov[0].iov_base = &req;
iov[0].iov_len = sizeof (req);
iov[1].iov_base = arg;
iov[1].iov_len = req.key_len;
- nbytes = TEMP_FAILURE_RETRY (writev (sock, iov, 2));
+ ssize_t nbytes = TEMP_FAILURE_RETRY (writev (sock, iov, 2));
+
+ if (nbytes != iov[0].iov_len + iov[1].iov_len)
+ {
+ int err = errno;
+ close (sock);
+ error (EXIT_FAILURE, err, _("write incomplete"));
+ }
+
+ /* Wait for ack. Older nscd just closed the socket when
+ prune_cache finished, silently ignore that. */
+ int32_t resp = 0;
+ nbytes = TEMP_FAILURE_RETRY (read (sock, &resp, sizeof (resp)));
+ if (nbytes != 0 && nbytes != sizeof (resp))
+ {
+ int err = errno;
+ close (sock);
+ error (EXIT_FAILURE, err, _("cannot read invalidate ACK"));
+ }
close (sock);
- exit (nbytes != iov[0].iov_len + iov[1].iov_len
- ? EXIT_FAILURE : EXIT_SUCCESS);
+ if (resp != 0)
+ error (EXIT_FAILURE, resp, _("invalidation failed"));
+
+ exit (0);
}
case 't':
diff --git a/nscd/nscd.h b/nscd/nscd.h
index 8b95630807..5c2ff3a95b 100644
--- a/nscd/nscd.h
+++ b/nscd/nscd.h
@@ -58,6 +58,7 @@ typedef enum
struct database_dyn
{
pthread_rwlock_t lock;
+ pthread_mutex_t prunelock;
int enabled;
int check_file;
@@ -184,7 +185,7 @@ extern struct datahead *cache_search (request_type, void *key, size_t len,
extern int cache_add (int type, const void *key, size_t len,
struct datahead *packet, bool first,
struct database_dyn *table, uid_t owner);
-extern void prune_cache (struct database_dyn *table, time_t now);
+extern void prune_cache (struct database_dyn *table, time_t now, int fd);
/* pwdcache.c */
extern void addpwbyname (struct database_dyn *db, int fd, request_header *req,