[CRIU] [PATCH 14/15] bfd: Implement buffered writes

Andrew Vagin avagin at parallels.com
Mon Sep 29 03:36:39 PDT 2014


On Mon, Sep 29, 2014 at 12:50:29PM +0400, Pavel Emelyanov wrote:
> Dump times (top-5) look like
> 
> Before patch:
> 	writev:     1595  0.048337 (15.1%)
> 	openat:     1326  0.041976 (13.1%)
> 	 close:     1434  0.034661 (10.8%)
> 	  read:      988  0.028760 (9.0%)
> 	 wait4:      170  0.028271 (8.8%)
> 
> After patch:
> 	openat:     1326  0.040010 (16.4%)
> 	 close:     1434  0.030039 (12.3%)
> 	  read:      988  0.025827 (10.6%)
> 	 wait4:      170  0.025549 (10.5%)
> 	ptrace:      834  0.021624 (8.9%)
> 
> So write-s go away from top list (turn into 8th position).
> 
> Funny thing is that all object writes get merged with the
> magic writes, so the total amount of write()-s (not writev-s)
> in the strace remain intact :)
> 
> Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
> ---
>  bfd.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 70 insertions(+), 3 deletions(-)
> 
> diff --git a/bfd.c b/bfd.c
> index 2572679..0bc9a64 100644
> --- a/bfd.c
> +++ b/bfd.c
> @@ -84,10 +84,22 @@ int bfdopen(struct bfd *f)
>  	return 0;
>  }
>  
> +static int bflush(struct bfd *bfd);
> +
>  void bclose(struct bfd *f)
>  {
> -	if (bfd_buffered(f))
> +	if (bfd_buffered(f)) {
> +		if (bflush(f) < 0)
> +			/*
> +			 * FIXME -- propagate error up. It's
> +			 * hardly possible by returning and
> +			 * checking it, but setting a static
> +			 * flag, failing further bfdopen-s and
> +			 * checking one at the end would work.
> +			 */
> +			pr_err("Error flushing image\n");
>  		buf_put(&f->b);
> +	}

Nobody reads logs if the exit code is zero. I would prefer to return
error from here and check it.

>  	close(f->fd);
>  }
>  
> @@ -178,14 +190,69 @@ again:
>  	goto again;
>  }
>  
> +static int bflush(struct bfd *bfd)
> +{
> +	struct xbuf *b = &bfd->b;
> +	int ret;
> +
> +	if (!b->sz)
> +		return 0;
> +
> +	ret = write(bfd->fd, b->data, b->sz);
> +	if (ret != b->sz)

Can we print error here?

> +		return -1;
> +
> +	b->sz = 0;
> +	return 0;
> +}
> +
> +static int __bwrite(struct bfd *bfd, const void *buf, int size)
> +{
> +	struct xbuf *b = &bfd->b;
> +
> +	if (b->sz + size > BUFSIZE) {
> +		int ret;
> +		ret = bflush(bfd);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	if (size > BUFSIZE)
> +		return write(bfd->fd, buf, size);

Looks like you want to say that a caller whould get a proper errno and
print errors.

> +
> +	memcpy(b->data + b->sz, buf, size);
> +	b->sz += size;
> +	return size;
> +}
> +
>  int bwrite(struct bfd *bfd, const void *buf, int size)
>  {
> -	return write(bfd->fd, buf, size);
> +	if (!bfd_buffered(bfd))
> +		return write(bfd->fd, buf, size);
> +
> +	return __bwrite(bfd, buf, size);
>  }
>  
>  int bwritev(struct bfd *bfd, const struct iovec *iov, int cnt)
>  {
> -	return writev(bfd->fd, iov, cnt);
> +	int i, written = 0;
> +
> +	if (!bfd_buffered(bfd))
> +		return writev(bfd->fd, iov, cnt);
> +
> +	for (i = 0; i < cnt; i++) {
> +		int ret;
> +
> +		ret = __bwrite(bfd, (const void *)iov[i].iov_base, iov[i].iov_len);
> +		if (ret < 0)
> +			return ret;

		written += ret;

> +		if (ret < iov[i].iov_len)
> +			break;
> +
> +		written += ret;

It should be moved upper.

> +	}
> +
> +	return written;
>  }
>  
>  int bread(struct bfd *bfd, void *buf, int size)
> -- 
> 1.8.4.2
> 
> 
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu


More information about the CRIU mailing list