[systemd-devel] [PATCH 2/5] hostnamed: watch for transient hostname changes

Lennart Poettering lennart at poettering.net
Mon Feb 24 07:32:46 PST 2014


On Mon, 24.02.14 15:59, Michal Sekletar (msekleta at redhat.com) wrote:

> hostnamed parses its state information at the startup time and doesn't update
> it. This might lead to the situation when we are presenting administrator with
> inaccurate information. We should watch for changes in the system and update our
> state information accordingly.

Hmm, so there has been a TODO list item for a while that suggests to
refresh all information we expose when the user asks for it. More
specifically, we should stat() check the configuration files on each
property request, to see if they changed mtime since the last time. And
for the hostname we should simply never cache anything and always simply
go to the kernel. That is cheap enough and wouldn't make any fancy
hostname watching necessary.

> ---
>  src/hostname/hostnamed.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 88 insertions(+)
> 
> diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
> index e57891b..045f24d 100644
> --- a/src/hostname/hostnamed.c
> +++ b/src/hostname/hostnamed.c
> @@ -24,6 +24,10 @@
>  #include <unistd.h>
>  #include <dlfcn.h>
>  
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +
>  #include "util.h"
>  #include "strv.h"
>  #include "def.h"
> @@ -46,8 +50,12 @@ enum {
>  typedef struct Context {
>          char *data[_PROP_MAX];
>          Hashmap *polkit_registry;
> +        int hostnamefd;
> +        sd_event_source *hostname_fd_event_source;
>  } Context;
>  
> +static const char *proc_hostname = "/proc/sys/kernel/hostname";
> +
>  static void context_reset(Context *c) {
>          int p;
>  
> @@ -59,11 +67,21 @@ static void context_reset(Context *c) {
>          }
>  }
>  
> +static void context_init(Context *c) {
> +        assert(c);
> +
> +        memzero(c, sizeof(*c));
> +
> +        c->hostnamefd = -1;
> +}
> +
>  static void context_free(Context *c, sd_bus *bus) {
>          assert(c);
>  
>          context_reset(c);
>          bus_verify_polkit_async_registry_free(bus, c->polkit_registry);
> +        sd_event_source_unref(c->hostname_fd_event_source);
> +        close_nointr_nofail(c->hostnamefd);
>  }
>  
>  static int context_read_data(Context *c) {
> @@ -592,6 +610,70 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
>          return 0;
>  }
>  
> +static int dispatch_hostname_change(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
> +        int r = 0;
> +        char hostname[HOST_NAME_MAX + 1] = {}, *t;
> +        Context *context = (Context *) userdata;
> +
> +        r = lseek(fd, 0, SEEK_SET);
> +        if (r < 0) {
> +                log_error("Failed to seek to begining of the file : %m");
> +                return -errno;
> +        }
> +
> +        r = read(fd, hostname, HOST_NAME_MAX);
> +        if (r < 0) {
> +                log_error("Failed to read hostname : %m");
> +                return -errno;
> +        }
> +
> +        strstrip(hostname);
> +
> +        t = strdup(hostname);
> +        if (!t)
> +                return log_oom();
> +        free(context->data[PROP_HOSTNAME]);
> +        context->data[PROP_HOSTNAME] = t;
> +
> +        return r;
> +}
> +
> +static int open_hostname(sd_event *event, Context *context) {
> +        int r = 0, fd;
> +
> +        assert(event);
> +        assert(context);
> +
> +        fd = open(proc_hostname, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
> +        if (fd < 0) {
> +                log_error("Failed to open %s : %m", proc_hostname);
> +                return -errno;
> +        }
> +
> +        context->hostnamefd = fd;
> +
> +        r = sd_event_add_io(event, &context->hostname_fd_event_source, fd, EPOLLHUP, dispatch_hostname_change, context);
> +        if (r < 0) {
> +                /* poll on /proc/sys/kernel/hostname not supported by kernel */
> +                if (r == -EPERM) {
> +                        log_warning("Failed to register hostname fd in event loop: %m. Ignoring.");
> +                        close_nointr_nofail(fd);
> +                        return 0;
> +                }
> +
> +                log_error("Failed to register hostname fd in event loop : %m");
> +                return r;
> +        }
> +
> +        r = sd_event_source_set_priority(context->hostname_fd_event_source, SD_EVENT_PRIORITY_IMPORTANT);
> +        if (r < 0) {
> +                log_error("Failed to set priority for hostname fd event source : %m");
> +                return r;
> +        }
> +
> +        return r;
> +}
> +
>  int main(int argc, char *argv[]) {
>          Context context = {};
>  
> @@ -621,6 +703,8 @@ int main(int argc, char *argv[]) {
>                  goto finish;
>          }
>  
> +        context_init(&context);
> +
>          r = sd_event_default(&event);
>          if (r < 0) {
>                  log_error("Failed to allocate event loop: %s", strerror(-r));
> @@ -639,6 +723,10 @@ int main(int argc, char *argv[]) {
>                  goto finish;
>          }
>  
> +        r = open_hostname(event, &context);
> +        if (r < 0)
> +                goto finish;
> +
>          r = bus_event_loop_with_idle(event, bus, "org.freedesktop.hostname1", DEFAULT_EXIT_USEC, NULL, NULL);
>          if (r < 0) {
>                  log_error("Failed to run event loop: %s", strerror(-r));


Lennart

-- 
Lennart Poettering, Red Hat


More information about the systemd-devel mailing list