summaryrefslogtreecommitdiff
path: root/nscd
diff options
context:
space:
mode:
authorThomas Schwinge <thomas@codesourcery.com>2013-05-23 23:37:00 +0200
committerThomas Schwinge <thomas@codesourcery.com>2013-05-23 23:37:00 +0200
commitf9e888643115b4b2f28853ebd1733f4410fb8839 (patch)
tree58c69f6cef623679080e8933b6c79880bfbd7cb8 /nscd
parentd78eef6ebc008f784f501ce208bef12c6eafda27 (diff)
parentb934acf0e93c5a220551ed6e686bb9d45a24a8cc (diff)
Merge branch 'baseline' into refs/top-bases/tschwinge/Roger_Whittaker
Diffstat (limited to 'nscd')
-rw-r--r--nscd/connections.c150
-rw-r--r--nscd/nscd-client.h5
-rw-r--r--nscd/nscd.h7
3 files changed, 88 insertions, 74 deletions
diff --git a/nscd/connections.c b/nscd/connections.c
index f6e2328637..56c327971b 100644
--- a/nscd/connections.c
+++ b/nscd/connections.c
@@ -976,9 +976,25 @@ cannot change socket to nonblocking mode: %s"),
}
+/* Register the file in FINFO as a traced file for the database DBS[DBIX].
+
+ We support registering multiple files per database. Each call to
+ register_traced_file adds to the list of registered files.
+
+ When we prune the database, either through timeout or a request to
+ invalidate, we will check to see if any of the registered files has changed.
+ When we accept new connections to handle a cache request we will also
+ check to see if any of the registered files has changed.
+
+ If we have inotify support then we install an inotify fd to notify us of
+ file deletion or modification, both of which will require we invalidate
+ the cache for the database. Without inotify support we stat the file and
+ store st_mtime to determine if the file has been modified. */
void
register_traced_file (size_t dbidx, struct traced_file *finfo)
{
+ /* If the database is disabled or file checking is disabled
+ then ignore the registration. */
if (! dbs[dbidx].enabled || ! dbs[dbidx].check_file)
return;
@@ -1859,7 +1875,7 @@ fd_ready (int fd)
/* Check whether restarting should happen. */
-static inline int
+static bool
restart_p (time_t now)
{
return (paranoia && readylist == NULL && nready == nthreads
@@ -1870,6 +1886,63 @@ restart_p (time_t now)
/* Array for times a connection was accepted. */
static time_t *starttime;
+#ifdef HAVE_INOTIFY
+/* Inotify event for changed file. */
+union __inev
+{
+ struct inotify_event i;
+# ifndef PATH_MAX
+# define PATH_MAX 1024
+# endif
+ char buf[sizeof (struct inotify_event) + PATH_MAX];
+};
+
+/* Process the inotify event in INEV. If the event matches any of the files
+ registered with a database then mark that database as requiring its cache
+ to be cleared. We indicate the cache needs clearing by setting
+ TO_CLEAR[DBCNT] to true for the matching database. */
+static inline void
+inotify_check_files (bool *to_clear, union __inev *inev)
+{
+ /* Check which of the files changed. */
+ for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
+ {
+ struct traced_file *finfo = dbs[dbcnt].traced_files;
+
+ while (finfo != NULL)
+ {
+ /* Inotify event watch descriptor matches. */
+ if (finfo->inotify_descr == inev->i.wd)
+ {
+ /* Mark cache as needing to be cleared and reinitialize. */
+ to_clear[dbcnt] = true;
+ if (finfo->call_res_init)
+ res_init ();
+ return;
+ }
+
+ finfo = finfo->next;
+ }
+ }
+}
+
+/* If an entry in the array of booleans TO_CLEAR is TRUE then clear the cache
+ for the associated database, otherwise do nothing. The TO_CLEAR array must
+ have LASTDB entries. */
+static inline void
+clear_db_cache (bool *to_clear)
+{
+ for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
+ if (to_clear[dbcnt])
+ {
+ pthread_mutex_lock (&dbs[dbcnt].prune_lock);
+ dbs[dbcnt].clear_cache = 1;
+ pthread_mutex_unlock (&dbs[dbcnt].prune_lock);
+ pthread_cond_signal (&dbs[dbcnt].prune_cond);
+ }
+}
+
+#endif
static void
__attribute__ ((__noreturn__))
@@ -1976,15 +2049,10 @@ main_loop_poll (void)
if (conns[1].revents != 0)
{
bool to_clear[lastdb] = { false, };
- union
- {
-# ifndef PATH_MAX
-# define PATH_MAX 1024
-# endif
- struct inotify_event i;
- char buf[sizeof (struct inotify_event) + PATH_MAX];
- } inev;
+ union __inev inev;
+ /* Read all inotify events for files registered via
+ register_traced_file(). */
while (1)
{
ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev,
@@ -2010,35 +2078,11 @@ disabled inotify after read error %d"),
}
/* Check which of the files changed. */
- for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
- {
- struct traced_file *finfo = dbs[dbcnt].traced_files;
-
- while (finfo != NULL)
- {
- if (finfo->inotify_descr == inev.i.wd)
- {
- to_clear[dbcnt] = true;
- if (finfo->call_res_init)
- res_init ();
- goto next;
- }
-
- finfo = finfo->next;
- }
- }
- next:;
+ inotify_check_files (to_clear, &inev);
}
/* Actually perform the cache clearing. */
- for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
- if (to_clear[dbcnt])
- {
- pthread_mutex_lock (&dbs[dbcnt].prune_lock);
- dbs[dbcnt].clear_cache = 1;
- pthread_mutex_unlock (&dbs[dbcnt].prune_lock);
- pthread_cond_signal (&dbs[dbcnt].prune_cond);
- }
+ clear_db_cache (to_clear);
--n;
}
@@ -2208,12 +2252,10 @@ main_loop_epoll (int efd)
else if (revs[cnt].data.fd == inotify_fd)
{
bool to_clear[lastdb] = { false, };
- union
- {
- struct inotify_event i;
- char buf[sizeof (struct inotify_event) + PATH_MAX];
- } inev;
+ union __inev inev;
+ /* Read all inotify events for files registered via
+ register_traced_file(). */
while (1)
{
ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev,
@@ -2235,35 +2277,11 @@ main_loop_epoll (int efd)
}
/* Check which of the files changed. */
- for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
- {
- struct traced_file *finfo = dbs[dbcnt].traced_files;
-
- while (finfo != NULL)
- {
- if (finfo->inotify_descr == inev.i.wd)
- {
- to_clear[dbcnt] = true;
- if (finfo->call_res_init)
- res_init ();
- goto next;
- }
-
- finfo = finfo->next;
- }
- }
- next:;
+ inotify_check_files(to_clear, &inev);
}
/* Actually perform the cache clearing. */
- for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
- if (to_clear[dbcnt])
- {
- pthread_mutex_lock (&dbs[dbcnt].prune_lock);
- dbs[dbcnt].clear_cache = 1;
- pthread_mutex_unlock (&dbs[dbcnt].prune_lock);
- pthread_cond_signal (&dbs[dbcnt].prune_cond);
- }
+ clear_db_cache (to_clear);
}
# endif
# ifdef HAVE_NETLINK
diff --git a/nscd/nscd-client.h b/nscd/nscd-client.h
index 11964f607d..360852b2a6 100644
--- a/nscd/nscd-client.h
+++ b/nscd/nscd-client.h
@@ -362,8 +362,9 @@ extern struct mapped_database *__nscd_get_map_ref (request_type type,
extern void __nscd_unmap (struct mapped_database *mapped);
/* Drop reference of mapping. */
-static inline int __nscd_drop_map_ref (struct mapped_database *map,
- int *gc_cycle)
+static int
+__attribute__ ((unused))
+__nscd_drop_map_ref (struct mapped_database *map, int *gc_cycle)
{
if (map != NO_MAPPING)
{
diff --git a/nscd/nscd.h b/nscd/nscd.h
index 46d0433286..cbd402a958 100644
--- a/nscd/nscd.h
+++ b/nscd/nscd.h
@@ -200,12 +200,7 @@ extern gid_t old_gid;
/* Prototypes for global functions. */
/* Wrapper functions with error checking for standard functions. */
-extern void *xmalloc (size_t n)
- __attribute_malloc__ __attribute_alloc_size (1);
-extern void *xcalloc (size_t n, size_t s)
- __attribute_malloc__ __attribute_alloc_size (1, 2);
-extern void *xrealloc (void *o, size_t n)
- __attribute_malloc__ __attribute_alloc_size (2);
+#include <programs/xmalloc.h>
/* nscd.c */
extern void termination_handler (int signum) __attribute__ ((__noreturn__));