From 319b9ad4bccedb2a6b1a222cf446e873b2bc6de1 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Mon, 11 Jul 2011 14:50:24 -0400 Subject: 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. --- nscd/connections.c | 165 ++++++++++++++++++++++++++--------------------------- 1 file changed, 82 insertions(+), 83 deletions(-) (limited to 'nscd/connections.c') diff --git a/nscd/connections.c b/nscd/connections.c index 1e47931..6e48869 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:; } -- cgit v1.1