[CRIU] [PATCH 15/15] bfd: Implement buffered reads

Pavel Emelyanov xemul at parallels.com
Mon Sep 29 01:50:44 PDT 2014


The restore times look like

Before patch:
	  futex:      370  3.554482 (84.2%)
	 umount:       41  0.234796 (5.6%)
	   read:     4737  0.113987 (2.7%)
	recvmsg:       43  0.100083 (2.4%)
	  wait4:       10  0.033344 (0.8%)

After patch:
	  futex:      187  1.547642 (72.9%)
	 umount:       41  0.234595 (11.0%)
	recvmsg:       43  0.075738 (3.6%)
	  flock:       42  0.038696 (1.8%)
	  clone:       35  0.037699 (1.8%)

Most of the time we wait for other processes to restore,
but that's OK (would only affect parallel restore). And
we see that read-s really go away (onto 7th position).

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
 bfd.c | 41 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 38 insertions(+), 3 deletions(-)

diff --git a/bfd.c b/bfd.c
index 0bc9a64..55a0cfa 100644
--- a/bfd.c
+++ b/bfd.c
@@ -6,6 +6,7 @@
 #include <fcntl.h>
 #include <sys/uio.h>
 
+#include "bug.h"
 #include "log.h"
 #include "bfd.h"
 #include "list.h"
@@ -89,6 +90,12 @@ static int bflush(struct bfd *bfd);
 void bclose(struct bfd *f)
 {
 	if (bfd_buffered(f)) {
+		/*
+		 * FIXME -- when we bread from images we don't
+		 * need to flush. This call doesn't fail simply
+		 * becase we read _all_ data from them and the
+		 * b->sz would be 0 by the time we close them.
+		 */
 		if (bflush(f) < 0)
 			/*
 			 * FIXME -- propagate error up. It's
@@ -121,7 +128,7 @@ static int brefill(struct bfd *f)
 		return 0;
 
 	b->sz += ret;
-	return 0;
+	return 1;
 }
 
 static char *strnchr(char *str, unsigned int len, char c)
@@ -182,7 +189,7 @@ again:
 	ss = b->sz;
 
 	/* no full line in the buffer -- refill one */
-	if (brefill(f))
+	if (brefill(f) < 0)
 		return BREADERR;
 
 	refilled = true;
@@ -257,5 +264,33 @@ int bwritev(struct bfd *bfd, const struct iovec *iov, int cnt)
 
 int bread(struct bfd *bfd, void *buf, int size)
 {
-	return read(bfd->fd, buf, size);
+	struct xbuf *b = &bfd->b;
+	int more = 1, filled = 0;
+
+	if (!bfd_buffered(bfd))
+		return read(bfd->fd, buf, size);
+
+	while (more > 0) {
+		int chunk;
+
+		chunk = size - filled;
+		if (chunk > b->sz)
+			chunk = b->sz;
+
+		if (chunk) {
+			memcpy(buf + filled, b->data, chunk);
+			b->data += chunk;
+			b->sz -= chunk;
+			filled += chunk;
+		}
+
+		if (filled < size)
+			more = brefill(bfd);
+		else {
+			BUG_ON(filled > size);
+			more = 0;
+		}
+	}
+
+	return more < 0 ? more : filled;
 }
-- 
1.8.4.2




More information about the CRIU mailing list