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

2014-02-24 Thread Lennart Poettering
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 = 

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

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

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) {