This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Make Fedora not require reboots on wireless network changes


GNU ChangeLog:

2010-09-13  Colin Walters  <walters@verbum.org>

	* resolv/res_libc.c (__res_maybe_init): If the DYNAMIC
	option is specified, call _res_dynamic_check() to re-stat
	the resolv.conf file.
	(_res_dynamic_check): New function.
	* resolv/res_init.c: Check for "dynamic" option.
	* resolv/resolv.h: Define #RES_DYNAMIC.

Patch is attached, for convenience I've pasted the git log inline, which has
the justification and details:

[PATCH] resolv: Add a new "dynamic" option which tells us to re-stat the file

Various operating system vendors have been shipping variants of a
patch which stat()s resolv.conf on every gethostbyname() call.  Actually,
effectively every important OS vendor shipping glibc does, except Fedora.

The reason for this is simply that on mobile devices, nameservers can
change, and having to restart all applications and processes which
have cached resolv.conf data for this is simply broken.  (NSCD exists,
but is considered deprecated by SSSD, which is now in Fedora 13 by
default.)  SSSD does not do name service caching.

Another simple argument for this patch - the canonical location of the
data is in /etc/resolv.conf; if glibc is reading it into memory
without a mechanism for invalidating that copy - it's not a cache,
it's a copy, which is a bug.

The intent of this patch is that in e.g. Fedora, NetworkManager's
generated resolv.conf file will include this if it gets any of its
data from DHCP.  Otherwise, it can omit the option, and processes
won't have to pay the cost of the stat() (assuming it was even a real
concern to begin with).

Note that NetworkManager will *also* be adding support for different
userspace DNS caching frameworks like dnsmasq, but having this patch
in the C library simply makes sense - we won't fail if there's no
running DNS cacher, which certainly seems possible for early-boot
scenarios.

>From 8b16bc9a70e52a0dc9e6051925c82d0e6aefcd90 Mon Sep 17 00:00:00 2001
From: Colin Walters <walters@verbum.org>
Date: Fri, 18 Jun 2010 16:19:12 -0400
Subject: [PATCH] resolv: Add a new "dynamic" option which tells us to re-stat the file

Various operating system vendors have been shipping variants of a
patch which stat()s resolv.conf on every gethostbyname() call.  Actually,
effectively every important OS vendor shipping glibc does, except Fedora.

The reason for this is simply that on mobile devices, nameservers can
change, and having to restart all applications and processes which
have cached resolv.conf data for this is simply broken.  (NSCD exists,
but is considered deprecated by SSSD, which is now in Fedora 13 by
default.)  SSSD does not do name service caching.

Another simple argument for this patch - the canonical location of the
data is in /etc/resolv.conf; if glibc is reading it into memory
without a mechanism for invalidating that copy - it's not a cache,
it's a copy, which is a bug.

The intent of this patch is that in e.g. Fedora, NetworkManager's
generated resolv.conf file will include this if it gets any of its
data from DHCP.  Otherwise, it can omit the option, and processes
won't have to pay the cost of the stat() (assuming it was even a real
concern to begin with).

Note that NetworkManager will *also* be adding support for different
userspace DNS caching frameworks like dnsmasq, but having this patch
in the C library simply makes sense - we won't fail if there's no
running DNS cacher, which certainly seems possible for early-boot
scenarios.
---
 resolv/res_init.c |    2 ++
 resolv/res_libc.c |   26 ++++++++++++++++++++++++++
 resolv/resolv.h   |    1 +
 3 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/resolv/res_init.c b/resolv/res_init.c
index 202569d..889ec82 100644
--- a/resolv/res_init.c
+++ b/resolv/res_init.c
@@ -533,6 +533,8 @@ res_setoptions(res_state statp, const char *options, const char *source) {
 			statp->options &= ~RES_NOIP6DOTINT;
 		} else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) {
 			statp->options |= RES_ROTATE;
+		} else if (!strncmp(cp, "dynamic", sizeof("dynamic") - 1)) {
+			statp->options |= RES_DYNAMIC;
 		} else if (!strncmp(cp, "no-check-names",
 				    sizeof("no-check-names") - 1)) {
 			statp->options |= RES_NOCHECKNAME;
diff --git a/resolv/res_libc.c b/resolv/res_libc.c
index 810fbc8..ad4862c 100644
--- a/resolv/res_libc.c
+++ b/resolv/res_libc.c
@@ -89,12 +89,38 @@ res_init(void) {
 	return (__res_vinit(&_res, 1));
 }
 
+/* If the DYNAMIC option is set, we stat the file, and see if its
+ * mtime has changed.  If so, request an initialization.
+ */
+static void
+_res_dynamic_check (void)
+{
+	static time_t last_mtime, last_check;
+	time_t now;
+	struct stat statbuf;
+
+	time (&now);
+	if (now != last_check) {
+		last_check = now;
+		if (stat (_PATH_RESCONF, &statbuf) == 0 && last_mtime != statbuf.st_mtime) {
+			last_mtime = statbuf.st_mtime;
+			atomicinclock (lock);
+			atomicinc (__res_initstamp);
+			atomicincunlock (lock);
+		}
+	}
+}
+
 /* Initialize resp if RES_INIT is not yet set or if res_init in some other
    thread requested re-initializing.  */
 int
 __res_maybe_init (res_state resp, int preinit)
 {
 	if (resp->options & RES_INIT) {
+		if (resp->options & RES_DYNAMIC) {
+			_res_dynamic_check ();
+		}
+
 		if (__res_initstamp != resp->_u._ext.initstamp) {
 			if (resp->nscount > 0)
 				__res_iclose (resp, true);
diff --git a/resolv/resolv.h b/resolv/resolv.h
index e49c29d..8f4a202 100644
--- a/resolv/resolv.h
+++ b/resolv/resolv.h
@@ -219,6 +219,7 @@ struct res_sym {
 #define RES_SNGLKUPREOP	0x00400000	/* -"-, but open new socket for each
 					   request */
 #define RES_USE_DNSSEC	0x00800000	/* use DNSSEC using OK bit in OPT */
+#define RES_DYNAMIC	0x01000000	/* check for changes in resolv.conf */
 
 #define RES_DEFAULT	(RES_RECURSE|RES_DEFNAMES|RES_DNSRCH|RES_NOIP6DOTINT)
 
-- 
1.7.2.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]