On Mon, 24.02.14 15:59, Michal Sekletar (msekl...@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
_______________________________________________
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel

Reply via email to