[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