summaryrefslogtreecommitdiff
path: root/nscd
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@gmail.com>2011-07-11 14:50:24 -0400
committerUlrich Drepper <drepper@gmail.com>2011-07-11 14:50:24 -0400
commit319b9ad4bccedb2a6b1a222cf446e873b2bc6de1 (patch)
tree7951727c0dbd4394af52715e226745986e8beeb4 /nscd
parent23bee3e8677c9357662ce789ed77fe25f3991c66 (diff)
downloadglibc-319b9ad4bccedb2a6b1a222cf446e873b2bc6de1.tar.gz
Generalize framework to register monitoring of files in nscd
nscd can clear caches when certain files change. The list of files was hardcoded so far and worked for nss_files and nss_dns and those modules which need no monitoring. nss_db, for instance, has its own set of files to monitor. Now the NSS modules themselves can request that certain files are monitored.
Diffstat (limited to 'nscd')
-rw-r--r--nscd/cache.c46
-rw-r--r--nscd/connections.c165
-rw-r--r--nscd/nscd.c18
-rw-r--r--nscd/nscd.h19
4 files changed, 144 insertions, 104 deletions
diff --git a/nscd/cache.c b/nscd/cache.c
index ebc6e4c0d6..58f0bcc5f1 100644
--- a/nscd/cache.c
+++ b/nscd/cache.c
@@ -264,28 +264,40 @@ prune_cache (struct database_dyn *table, time_t now, int fd)
/* If we check for the modification of the underlying file we invalidate
the entries also in this case. */
- if (table->inotify_descr < 0 && table->check_file && now != LONG_MAX)
+ if (table->check_file && now != LONG_MAX)
{
- struct stat64 st;
+ struct traced_file *runp = table->traced_files;
- if (stat64 (table->filename, &st) < 0)
+ while (runp != NULL)
{
- char buf[128];
- /* We cannot stat() the file, disable file checking if the
- file does not exist. */
- dbg_log (_("cannot stat() file `%s': %s"),
- table->filename, strerror_r (errno, buf, sizeof (buf)));
- if (errno == ENOENT)
- table->check_file = 0;
- }
- else
- {
- if (st.st_mtime != table->file_mtime)
+#ifdef HAVE_INOTIFY
+ if (runp->inotify_descr == -1)
+#endif
{
- /* The file changed. Invalidate all entries. */
- now = LONG_MAX;
- table->file_mtime = st.st_mtime;
+ struct stat64 st;
+
+ if (stat64 (runp->fname, &st) < 0)
+ {
+ char buf[128];
+ /* We cannot stat() the file, disable file checking if the
+ file does not exist. */
+ dbg_log (_("cannot stat() file `%s': %s"),
+ runp->fname, strerror_r (errno, buf, sizeof (buf)));
+ if (errno == ENOENT)
+ table->check_file = 0;
+ }
+ else
+ {
+ if (st.st_mtime != table->file_mtime)
+ {
+ /* The file changed. Invalidate all entries. */
+ now = LONG_MAX;
+ table->file_mtime = st.st_mtime;
+ }
+ }
}
+
+ runp = runp->next;
}
}
diff --git a/nscd/connections.c b/nscd/connections.c
index 1e47931bd2..6e48869c68 100644
--- a/nscd/connections.c
+++ b/nscd/connections.c
@@ -117,8 +117,6 @@ struct database_dyn dbs[lastdb] =
.shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE,
.suggested_module = DEFAULT_SUGGESTED_MODULE,
- .reset_res = 0,
- .filename = "/etc/passwd",
.db_filename = _PATH_NSCD_PASSWD_DB,
.disabled_iov = &pwd_iov_disabled,
.postimeout = 3600,
@@ -138,8 +136,6 @@ struct database_dyn dbs[lastdb] =
.shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE,
.suggested_module = DEFAULT_SUGGESTED_MODULE,
- .reset_res = 0,
- .filename = "/etc/group",
.db_filename = _PATH_NSCD_GROUP_DB,
.disabled_iov = &grp_iov_disabled,
.postimeout = 3600,
@@ -159,8 +155,6 @@ struct database_dyn dbs[lastdb] =
.shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE,
.suggested_module = DEFAULT_SUGGESTED_MODULE,
- .reset_res = 1,
- .filename = "/etc/hosts",
.db_filename = _PATH_NSCD_HOSTS_DB,
.disabled_iov = &hst_iov_disabled,
.postimeout = 3600,
@@ -180,8 +174,6 @@ struct database_dyn dbs[lastdb] =
.shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE,
.suggested_module = DEFAULT_SUGGESTED_MODULE,
- .reset_res = 0,
- .filename = "/etc/services",
.db_filename = _PATH_NSCD_SERVICES_DB,
.disabled_iov = &serv_iov_disabled,
.postimeout = 28800,
@@ -232,10 +224,7 @@ static int sock;
#ifdef HAVE_INOTIFY
/* Inotify descriptor. */
-static int inotify_fd = -1;
-
-/* Watch descriptor for resolver configuration file. */
-static int resolv_conf_descr = -1;
+int inotify_fd = -1;
#endif
#ifndef __ASSUME_SOCK_CLOEXEC
@@ -523,19 +512,6 @@ nscd_init (void)
/* No configuration for this value, assume a default. */
nthreads = 4;
-#ifdef HAVE_INOTIFY
- /* Use inotify to recognize changed files. */
- inotify_fd = inotify_init1 (IN_NONBLOCK);
-# ifndef __ASSUME_IN_NONBLOCK
- if (inotify_fd == -1 && errno == ENOSYS)
- {
- inotify_fd = inotify_init ();
- if (inotify_fd != -1)
- fcntl (inotify_fd, F_SETFL, O_RDONLY | O_NONBLOCK);
- }
-# endif
-#endif
-
for (size_t cnt = 0; cnt < lastdb; ++cnt)
if (dbs[cnt].enabled)
{
@@ -840,40 +816,6 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
dbs[cnt].shared = 0;
assert (dbs[cnt].ro_fd == -1);
}
-
- dbs[cnt].inotify_descr = -1;
- if (dbs[cnt].check_file)
- {
-#ifdef HAVE_INOTIFY
- if (inotify_fd < 0
- || (dbs[cnt].inotify_descr
- = inotify_add_watch (inotify_fd, dbs[cnt].filename,
- IN_DELETE_SELF | IN_MODIFY)) < 0)
- /* We cannot notice changes in the main thread. */
-#endif
- {
- /* We need the modification date of the file. */
- struct stat64 st;
-
- if (stat64 (dbs[cnt].filename, &st) < 0)
- {
- /* We cannot stat() the file, disable file checking. */
- dbg_log (_("cannot stat() file `%s': %s"),
- dbs[cnt].filename, strerror (errno));
- dbs[cnt].check_file = 0;
- }
- else
- dbs[cnt].file_mtime = st.st_mtime;
- }
- }
-
-#ifdef HAVE_INOTIFY
- if (cnt == hstdb && inotify_fd >= -1)
- /* We also monitor the resolver configuration file. */
- resolv_conf_descr = inotify_add_watch (inotify_fd,
- _PATH_RESCONF,
- IN_DELETE_SELF | IN_MODIFY);
-#endif
}
/* Create the socket. */
@@ -940,12 +882,50 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
exit (1);
}
- /* Change to unprivileged uid/gid/groups if specifed in config file */
+ /* Change to unprivileged uid/gid/groups if specified in config file */
if (server_user != NULL)
finish_drop_privileges ();
}
+void
+register_traced_file (size_t dbidx, struct traced_file *finfo)
+{
+ if (! dbs[dbidx].check_file)
+ return;
+
+ if (__builtin_expect (debug_level > 0, 0))
+ dbg_log (_("register trace file %s for database %s"),
+ finfo->fname, dbnames[dbidx]);
+
+#ifdef HAVE_INOTIFY
+ if (inotify_fd < 0
+ || (finfo->inotify_descr = inotify_add_watch (inotify_fd, finfo->fname,
+ IN_DELETE_SELF
+ | IN_MODIFY)) < 0)
+#endif
+ {
+ /* We need the modification date of the file. */
+ struct stat64 st;
+
+ if (stat64 (finfo->fname, &st) < 0)
+ {
+ /* We cannot stat() the file, disable file checking. */
+ dbg_log (_("cannot stat() file `%s': %s"),
+ finfo->fname, strerror (errno));
+ return;
+ }
+
+ finfo->inotify_descr = -1;
+ finfo->mtime = st.st_mtime;
+ }
+
+ /* Queue up the file name. */
+ finfo->next = dbs[dbidx].traced_files;
+ dbs[dbidx].traced_files = finfo;
+}
+
+
/* Close the connections. */
void
close_sockets (void)
@@ -963,11 +943,20 @@ invalidate_cache (char *key, int fd)
for (number = pwddb; number < lastdb; ++number)
if (strcmp (key, dbnames[number]) == 0)
{
- if (dbs[number].reset_res)
- res_init ();
-
+ if (number == hstdb)
+ {
+ struct traced_file *runp = dbs[hstdb].traced_files;
+ while (runp != NULL)
+ if (runp->call_res_init)
+ {
+ res_init ();
+ break;
+ }
+ else
+ runp = runp->next;
+ }
break;
- }
+ }
if (number == lastdb)
{
@@ -1913,16 +1902,21 @@ disabled inotify after read error %d"),
/* Check which of the files changed. */
for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
- if (inev.i.wd == dbs[dbcnt].inotify_descr)
- {
- to_clear[dbcnt] = true;
- goto next;
- }
-
- if (inev.i.wd == resolv_conf_descr)
{
- res_init ();
- to_clear[hstdb] = true;
+ 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:;
}
@@ -2089,7 +2083,7 @@ main_loop_epoll (int efd)
while (1)
{
ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev,
- sizeof (inev)));
+ sizeof (inev)));
if (nb < (ssize_t) sizeof (struct inotify_event))
{
if (__builtin_expect (nb == -1 && errno != EAGAIN, 0))
@@ -2108,16 +2102,21 @@ main_loop_epoll (int efd)
/* Check which of the files changed. */
for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
- if (inev.i.wd == dbs[dbcnt].inotify_descr)
- {
- to_clear[dbcnt] = true;
- goto next;
- }
-
- if (inev.i.wd == resolv_conf_descr)
{
- res_init ();
- to_clear[hstdb] = true;
+ 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:;
}
diff --git a/nscd/nscd.c b/nscd/nscd.c
index c3d9fe6cef..4894cb2faa 100644
--- a/nscd/nscd.c
+++ b/nscd/nscd.c
@@ -46,6 +46,9 @@
#include "selinux.h"
#include "../nss/nsswitch.h"
#include <device-nrs.h>
+#ifdef HAVE_INOTIFY
+# include <sys/inotify.h>
+#endif
/* Get libc version number. */
#include <version.h>
@@ -272,8 +275,21 @@ main (int argc, char **argv)
/* Cleanup files created by a previous 'bind'. */
unlink (_PATH_NSCDSOCKET);
+#ifdef HAVE_INOTIFY
+ /* Use inotify to recognize changed files. */
+ inotify_fd = inotify_init1 (IN_NONBLOCK);
+# ifndef __ASSUME_IN_NONBLOCK
+ if (inotify_fd == -1 && errno == ENOSYS)
+ {
+ inotify_fd = inotify_init ();
+ if (inotify_fd != -1)
+ fcntl (inotify_fd, F_SETFL, O_RDONLY | O_NONBLOCK);
+ }
+# endif
+#endif
+
/* Make sure we do not get recursive calls. */
- __nss_disable_nscd ();
+ __nss_disable_nscd (register_traced_file);
/* Init databases. */
nscd_init ();
diff --git a/nscd/nscd.h b/nscd/nscd.h
index 5e3c865a29..c15e88bb6f 100644
--- a/nscd/nscd.h
+++ b/nscd/nscd.h
@@ -62,6 +62,17 @@ typedef enum
#define MAX_STACK_USE ((8 * NSCD_THREAD_STACKSIZE) / 10)
+/* Registered filename used to fill database. */
+struct traced_file
+{
+ time_t mtime;
+ struct traced_file *next;
+ int call_res_init;
+ int inotify_descr;
+ char fname[];
+};
+
+
/* Structure describing dynamic part of one database. */
struct database_dyn
{
@@ -73,13 +84,11 @@ struct database_dyn
int enabled;
int check_file;
- int inotify_descr;
int clear_cache;
int persistent;
int shared;
int propagate;
- int reset_res;
- const char filename[16];
+ struct traced_file *traced_files;
const char *db_filename;
time_t file_mtime;
size_t suggested_module;
@@ -147,6 +156,9 @@ extern int nthreads;
/* Maximum number of threads to use. */
extern int max_nthreads;
+/* Inotify descriptor. */
+extern int inotify_fd;
+
/* User name to run server processes as. */
extern const char *server_user;
@@ -191,6 +203,7 @@ extern int nscd_open_socket (void);
/* connections.c */
extern void nscd_init (void);
+extern void register_traced_file (size_t dbidx, struct traced_file *finfo);
extern void close_sockets (void);
extern void start_threads (void) __attribute__ ((__noreturn__));