Subject: Faster Migration
To: None <port-xen@NetBSD.org>
From: Jed Davis <jdev@panix.com>
List: port-xen
Date: 09/15/2005 20:52:07
--=-=-=
Jed Davis <jdev@panix.com> writes:
> What I've been slowly leading up to: with this and the other three
> changes I've posted about today, I can successfully (and consistently)
> save and restore a Linux domU with a NetBSD dom0.
Live migration also works -- and non-live, for that matter. (I have
had a domain fail to suspend once, while running a process on the domU
that repeatedly wrote to 2MB of memory, but I haven't been able to
reproduce it, and it's likely not our problem anyway.)
But it's a bit slow, because xfrd reads from the network socket using
fread() on an _IONBF'ed stream; under NetBSD, this results in a
sequence of one-character reads. This behavior, as far as I can tell,
goes back all the way to V7 Unix; i.e., it's older than me.
So I've modified libxutil, which has its own IO indirection layer, to
switch to read(2) in the "unbuffered" case; the patch is attached.
--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment; filename=migrate-speed.patch
Content-Description: Have libxutil use read(2) instead of fread(3) for \"unbuffered\" I/O.
--- libxutil/file_stream.c.orig 2005-09-13 17:02:16.000000000 -0400
+++ libxutil/file_stream.c 2005-09-13 17:31:39.000000000 -0400
@@ -21,11 +21,13 @@
*/
#ifndef __KERNEL__
#include <stdio.h>
+#include <unistd.h>
#include <stdlib.h>
#include "allocate.h"
#include "file_stream.h"
static int file_read(IOStream *s, void *buf, size_t n);
+static int file_read_nbuf(IOStream *s, void* buf, size_t n);
static int file_write(IOStream *s, const void *buf, size_t n);
static int file_error(IOStream *s);
static int file_close(IOStream *s);
@@ -42,6 +44,16 @@
flush: file_flush,
};
+/** Methods used by a FILE* IOStream that's unbuffered. */
+static const IOMethods file_methods_nbuf = {
+ read: file_read_nbuf,
+ write: file_write,
+ error: file_error,
+ close: file_close,
+ free: file_free,
+ flush: file_flush,
+};
+
/** IOStream for stdin. */
static IOStream _iostdin = {
methods: &file_methods,
@@ -102,6 +114,7 @@
* @return 0 on success, non-zero otherwise
*/
int file_stream_setvbuf(IOStream *io, char *buf, int mode, size_t size){
+ io->methods = (mode == _IONBF) ? &file_methods_nbuf : &file_methods;
return setvbuf(get_file(io), buf, mode, size);
}
@@ -126,6 +139,15 @@
static int file_read(IOStream *s, void *buf, size_t n){
return fread(buf, 1, n, get_file(s));
}
+static int file_read_nbuf(IOStream *s, void *buf, size_t n){
+ int fd = fileno(get_file(s)), rv, nr=0;
+ while(n > nr) {
+ rv = read(fd, buf+nr, n-nr);
+ if (rv <= 0) break;
+ nr += rv;
+ }
+ return nr;
+}
/** Fush the underlying stream using fflush().
*
--=-=-=
--
(let ((C call-with-current-continuation)) (apply (lambda (x y) (x y)) (map
((lambda (r) ((C C) (lambda (s) (r (lambda l (apply (s s) l)))))) (lambda
(f) (lambda (l) (if (null? l) C (lambda (k) (display (car l)) ((f (cdr l))
(C k))))))) '((#\J #\d #\D #\v #\s) (#\e #\space #\a #\i #\newline)))))
--=-=-=--