[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 1/6] xenconsoled: introduce log file abstraction



Wei Liu writes ("[PATCH 1/6] xenconsoled: introduce log file abstraction"):
> It will be used to handle hypervsior log and guest console log.

Thanks.

> diff --git a/tools/console/daemon/logfile.h b/tools/console/daemon/logfile.h
> new file mode 100644
> index 0000000..87f3c51
...
> +#define LOGFILE_MAX_BACKUP_NUM  5
> +#define LOGFILE_MAX_SIZE        (1024*128)

These should surely be configurable by the end-user.

> +/* Append only abstraction for log file */
> +struct logfile_entry {
> +     int fd;
> +     off_t pos;
> +     off_t len;
> +};

AFAICT these types could be defined inside logfile.c, and `struct
logfile' declared (but not defined) here in the header file.

That would make the abstraction clearer.

> diff --git a/tools/console/daemon/logfile.c b/tools/console/daemon/logfile.c
> new file mode 100644
> index 0000000..ad73f8e
> --- /dev/null
> +++ b/tools/console/daemon/logfile.c
...
> +static void logfile_entry_free(struct logfile_entry *entry)
> +{
> +     if (!entry) return;
> +
> +     if (entry->fd >= 0) close(entry->fd);
> +     free(entry);
> +}

I do wonder whether it's actually worth having a whole separate struct
for an `entry'.  Each `struct logfile' has zero or one `struct
logfile_entry's but most of the time exactly one.

Eliminating the separate struct logfile_entry and folding it into
struct logfile would save some memory allocation (and associated error
handling).

> +     entry = calloc(1, sizeof(*entry));
> +     if (!entry) goto err;

This pattern calls close(0) on error!  Either declare that fd==0 means
"none here" (which would be sane IMO) or initialise fd=-1.

> +     entry->fd = open(path, O_CREAT|O_APPEND|O_WRONLY|O_CLOEXEC, mode);

I think we had concluded that O_CLOEXEC wasn't sufficiently portable ?
It's not needed here because xenconsoled does not exec.

> +     entry->pos = lseek(entry->fd, 0, SEEK_END);
> +     if (entry->pos == (off_t)-1) {
> +             dolog(LOG_ERR, "Unable to determine current file offset in %s",
> +                   path);
> +             goto err;
> +     }
> +
> +     if (fstat(entry->fd, &sb) < 0) {
> +             dolog(LOG_ERR, "Unable to fstat current file %s", path);
> +             goto err;
> +     }

I'm not sure why you need to keep track of `len' and `pos'
separately.  AFAICT len is never used.

> +struct logfile *logfile_new(const char *path, mode_t mode)
> +{

Why does logfile_new take a mode for which all callers pass 644 ?
Do we anticipate logs with different permissions ?

> +             if (rename(this, next) < 0 && errno != ENOENT) {
> +                     dolog(LOG_ERR, "Failed to rename %s to %s",
> +                           this, next);
> +                     goto err;
> +             }

If LOGFILE_MAX_BACKUP_NUM becomes configurable, this loop will have to
become more sophisticated.  I think it may have to count up and then
down again.

> +static ssize_t write_all(int fd, const char* buf, size_t len)
> +{
...

This is a copy of an identical function in io.c.

> +ssize_t logfile_append(struct logfile *file, const char *buf,
> +                    size_t len)
> +{
> +     ssize_t ret = 0;
> +
> +     while (len) {
> +             struct logfile_entry *entry = file->entry;
> +             size_t towrite = len;
> +             bool rollover = false;
> +
> +             if (entry->pos > file->maxlen) {
> +                     rollover = true;
> +                     towrite = 0;
> +             } else if (entry->pos + towrite > file->maxlen) {
> +                     towrite = file->maxlen - entry->pos;
> +             }
...
[and later]
> +             if ((entry->pos == file->maxlen && len) || rollover) {

This logic is rather tangled.  Why not

  maxwrite = file->maxlen - file->pos;
  if (towrite > maxwrite) {
      rollover = 1;
      towrite = maxwrite;
      if (towrite < 0)
          towrite = 0;
  }

and then later simply

    if (rollover) {

?

> +
> +             if (towrite) {
> +                     if (write_all(entry->fd, buf, towrite) != towrite) {
> +                             dolog(LOG_ERR, "Unable to write file %s",
> +                                   file->basepath);
> +                             return -1;
> +                     }
> +
> +                     len -= towrite;
> +                     buf += towrite;
> +                     ret += towrite;

I'm not a huge fan of this approach where several control variables
need to be kept in step.  You could save the beginning and end of the
buffer, and then you could do away with ret and no longer need to
modify len.

Ian.

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.