diff options
Diffstat (limited to 'nscd')
-rw-r--r-- | nscd/connections.c | 150 | ||||
-rw-r--r-- | nscd/nscd-client.h | 5 | ||||
-rw-r--r-- | nscd/nscd.h | 7 |
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__)); |