xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Ian Jackson <ian.jackson@eu.citrix.com>
To: Wei Liu <wei.liu2@citrix.com>
Cc: Xen-devel <xen-devel@lists.xenproject.org>
Subject: Re: [PATCH 1/6] xenconsoled: introduce log file abstraction
Date: Fri, 8 Jul 2016 17:50:24 +0100	[thread overview]
Message-ID: <22399.55760.873658.434157@mariner.uk.xensource.com> (raw)
In-Reply-To: <1465228781-22754-2-git-send-email-wei.liu2@citrix.com>

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@lists.xen.org
https://lists.xen.org/xen-devel

  reply	other threads:[~2016-07-08 16:50 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-06 15:59 [PATCH 0/6] xenconsoled: rotating log file abstration Wei Liu
2016-06-06 15:59 ` [PATCH 1/6] xenconsoled: introduce log file abstraction Wei Liu
2016-07-08 16:50   ` Ian Jackson [this message]
2016-06-06 15:59 ` [PATCH 2/6] xenconsoled: switch hypervisor log to use logfile abstraction Wei Liu
2016-07-08 16:58   ` Ian Jackson
2016-06-06 15:59 ` [PATCH 3/6] xenconsoled: switch guest " Wei Liu
2016-07-08 17:01   ` Ian Jackson
2016-06-06 15:59 ` [PATCH 4/6] xenconsoled: delete two now unused functions Wei Liu
2016-07-08 17:01   ` Ian Jackson
2016-06-06 15:59 ` [PATCH 5/6] xenconsoled: options to control log rotation Wei Liu
2016-07-08 17:02   ` Ian Jackson
2016-06-06 15:59 ` [PATCH 6/6] xenconsoled: handle --log-backups 0 in logfile_rollover Wei Liu
2016-07-08 17:03   ` Ian Jackson
2016-06-06 20:40 ` [PATCH 0/6] xenconsoled: rotating log file abstration Doug Goldstein
2016-06-07  8:07   ` Wei Liu
2016-06-07  9:44 ` David Vrabel
2016-06-07  9:55   ` Wei Liu
2016-06-07 10:17     ` David Vrabel
2016-06-07 10:21       ` Wei Liu
2016-06-07 10:29         ` David Vrabel
2016-06-07 10:34           ` Wei Liu
2016-06-07 10:35             ` David Vrabel
2016-06-07 10:43               ` Wei Liu
2016-07-02 10:24 ` Wei Liu
2016-07-04 17:07   ` Ian Jackson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=22399.55760.873658.434157@mariner.uk.xensource.com \
    --to=ian.jackson@eu.citrix.com \
    --cc=wei.liu2@citrix.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).