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

Michal Sekletar msekleta at redhat.com
Mon Feb 24 08:25:22 PST 2014


On Mon, Feb 24, 2014 at 04:32:46PM +0100, Lennart Poettering wrote:
> 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.

Very well then, I will rework this as you suggest.

Thanks,

Michal
> 
> > ---
> >  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