Commit b4640934 authored by Pavel Emelyanov's avatar Pavel Emelyanov

bfd: Implement buffered writes

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: 's avatarPavel Emelyanov <xemul@parallels.com>
Acked-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
parent b90ae65c
......@@ -94,10 +94,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);
}
close(f->fd);
}
......@@ -188,14 +200,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)
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);
memcpy(b->data + b->sz, buf, size);
b->sz += size;
return size;
}
int bwrite(struct bfd *bfd, const void *buf, int 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)
{
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;
}
return written;
}
int bread(struct bfd *bfd, void *buf, int size)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment