All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/29] Refactor xl code
@ 2017-02-24 16:12 Wei Liu
  2017-02-24 16:12 ` [PATCH 01/29] xl: remove accidentally committed hunk from Makefile Wei Liu
                   ` (28 more replies)
  0 siblings, 29 replies; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:12 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

xl_cmdimpl.c has become prohibitively large (almost 10k lines in one single
file). Try to split it up into multiple files according to the functionality of
the code.

I will run a full osstest flight before merging. Send the first version  out as
quick as possible to gather feedback because I know other people are also
touching this area of code.

Further improvements are certainly desired, for example we should probably give
functions better names, but this series is already very long, so let's save
that for another day.

Wei Liu (29):
  xl: remove accidentally committed hunk from Makefile
  xl: update copyright information
  xl: remove inclusion of libxl_osdeps.h
  xl: use <> variant to include Xen tools library headers
  xl: generate _paths.h
  xl: remove trailing spaces in xl_cmdimpl.c
  xl: lift a bunch of macros to xl_utils.h
  xl: move some helper functions to xl_utils.c
  xl: split out tmem related code to xl_tmem.c
  xl: split out xl_parse.[ch]
  xl: split out cpupool related code
  xl: split out flask related code
  xl: split out vtpm related code
  xl: split out block related code
  xl: split out network related code
  xl: split out usb related code
  xl: split out scheduler related code
  xl: split out pci related code
  xl: split out vcpu related code
  xl: split out cd related code
  xl: split out memory related code
  xl: split out psr related code
  xl: split out functions to print out information
  xl: split out vnc and console related code
  xl: split out miscellaneous functions
  xl: split out vm lifecycle control functions
  xl: split out save/restore related code
  xl: split out migration related code
  xl: merge xl_cmdimpl.c into xl.c

 .gitignore                |    1 +
 tools/xl/Makefile         |   19 +-
 tools/xl/xl.c             |   70 +-
 tools/xl/xl.h             |   77 +-
 tools/xl/xl_block.c       |  129 +
 tools/xl/xl_cd.c          |  114 +
 tools/xl/xl_cmdimpl.c     | 9642 ---------------------------------------------
 tools/xl/xl_cmdtable.c    |    4 +-
 tools/xl/xl_console.c     |  130 +
 tools/xl/xl_cpupool.c     |  624 +++
 tools/xl/xl_flask.c       |  153 +
 tools/xl/xl_info.c        |  925 +++++
 tools/xl/xl_mem.c         |  167 +
 tools/xl/xl_migrate.c     |  754 ++++
 tools/xl/xl_misc.c        |  355 ++
 tools/xl/xl_nic.c         |  172 +
 tools/xl/xl_parse.c       | 2052 ++++++++++
 tools/xl/xl_parse.h       |   65 +
 tools/xl/xl_pci.c         |  278 ++
 tools/xl/xl_psr.c         |  567 +++
 tools/xl/xl_saverestore.c |  273 ++
 tools/xl/xl_sched.c       |  888 +++++
 tools/xl/xl_sxp.c         |   10 +-
 tools/xl/xl_tmem.c        |  251 ++
 tools/xl/xl_usb.c         |  222 ++
 tools/xl/xl_utils.c       |  328 ++
 tools/xl/xl_utils.h       |  157 +
 tools/xl/xl_vcpu.c        |  337 ++
 tools/xl/xl_vmcontrol.c   | 1225 ++++++
 tools/xl/xl_vtpm.c        |  153 +
 30 files changed, 10474 insertions(+), 9668 deletions(-)
 create mode 100644 tools/xl/xl_block.c
 create mode 100644 tools/xl/xl_cd.c
 delete mode 100644 tools/xl/xl_cmdimpl.c
 create mode 100644 tools/xl/xl_console.c
 create mode 100644 tools/xl/xl_cpupool.c
 create mode 100644 tools/xl/xl_flask.c
 create mode 100644 tools/xl/xl_info.c
 create mode 100644 tools/xl/xl_mem.c
 create mode 100644 tools/xl/xl_migrate.c
 create mode 100644 tools/xl/xl_misc.c
 create mode 100644 tools/xl/xl_nic.c
 create mode 100644 tools/xl/xl_parse.c
 create mode 100644 tools/xl/xl_parse.h
 create mode 100644 tools/xl/xl_pci.c
 create mode 100644 tools/xl/xl_psr.c
 create mode 100644 tools/xl/xl_saverestore.c
 create mode 100644 tools/xl/xl_sched.c
 create mode 100644 tools/xl/xl_tmem.c
 create mode 100644 tools/xl/xl_usb.c
 create mode 100644 tools/xl/xl_utils.c
 create mode 100644 tools/xl/xl_utils.h
 create mode 100644 tools/xl/xl_vcpu.c
 create mode 100644 tools/xl/xl_vmcontrol.c
 create mode 100644 tools/xl/xl_vtpm.c

-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [PATCH 01/29] xl: remove accidentally committed hunk from Makefile
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
@ 2017-02-24 16:12 ` Wei Liu
  2017-02-27 15:53   ` Ian Jackson
  2017-02-24 16:12 ` [PATCH 02/29] xl: update copyright information Wei Liu
                   ` (27 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:12 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

It was never intended to be committed. Lucky the high level Makefile was
correct so it didn't cause us problem when building xl.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index d4b862c9b9..32dff40584 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -20,12 +20,6 @@ $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
 $(XL_OBJS): CFLAGS += -include $(XEN_ROOT)/tools/config.h # libxl_json.h needs it.
 
-# libxenlight should be built before building xl
-.PHONY: libxl
-libxl:
-	$(MAKE) -C $(XEN_ROOT)/tools/libxl
-$(XL_OBJS): libxl
-
 .PHONY: all
 all: xl
 
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 02/29] xl: update copyright information
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
  2017-02-24 16:12 ` [PATCH 01/29] xl: remove accidentally committed hunk from Makefile Wei Liu
@ 2017-02-24 16:12 ` Wei Liu
  2017-02-27 15:54   ` Ian Jackson
  2017-02-24 16:12 ` [PATCH 03/29] xl: remove inclusion of libxl_osdeps.h Wei Liu
                   ` (26 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:12 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/xl.c          | 4 +---
 tools/xl/xl.h          | 2 +-
 tools/xl/xl_cmdimpl.c  | 4 +---
 tools/xl/xl_cmdtable.c | 2 +-
 tools/xl/xl_sxp.c      | 4 +---
 5 files changed, 5 insertions(+), 11 deletions(-)

diff --git a/tools/xl/xl.c b/tools/xl/xl.c
index a272258155..4bc9648b71 100644
--- a/tools/xl/xl.c
+++ b/tools/xl/xl.c
@@ -1,7 +1,5 @@
 /*
- * Copyright (C) 2009      Citrix Ltd.
- * Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
- * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
+ * Copyright 2009-2017 Citrix Ltd and other contributors
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published
diff --git a/tools/xl/xl.h b/tools/xl/xl.h
index 0a8c8133cf..84dd2a9265 100644
--- a/tools/xl/xl.h
+++ b/tools/xl/xl.h
@@ -1,5 +1,5 @@
 /*
- * Author Yang Hongyang <yanghy@cn.fujitsu.com>
+ * Copyright 2009-2017 Citrix Ltd and other contributors
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index 0add5dcc5e..a83739942c 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -1,7 +1,5 @@
 /*
- * Copyright (C) 2009      Citrix Ltd.
- * Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
- * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
+ * Copyright 2009-2017 Citrix Ltd and other contributors
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published
diff --git a/tools/xl/xl_cmdtable.c b/tools/xl/xl_cmdtable.c
index 588d5d9604..ddcd6c2423 100644
--- a/tools/xl/xl_cmdtable.c
+++ b/tools/xl/xl_cmdtable.c
@@ -1,5 +1,5 @@
 /*
- * Author Yang Hongyang <yanghy@cn.fujitsu.com>
+ * Copyright 2009-2017 Citrix Ltd and other contributors
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published
diff --git a/tools/xl/xl_sxp.c b/tools/xl/xl_sxp.c
index a8c127b439..b67c0ae999 100644
--- a/tools/xl/xl_sxp.c
+++ b/tools/xl/xl_sxp.c
@@ -1,7 +1,5 @@
 /*
- * Copyright (C) 2009      Citrix Ltd.
- * Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
- * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
+ * Copyright 2009-2017 Citrix Ltd and other contributors
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 03/29] xl: remove inclusion of libxl_osdeps.h
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
  2017-02-24 16:12 ` [PATCH 01/29] xl: remove accidentally committed hunk from Makefile Wei Liu
  2017-02-24 16:12 ` [PATCH 02/29] xl: update copyright information Wei Liu
@ 2017-02-24 16:12 ` Wei Liu
  2017-02-27 15:53   ` Ian Jackson
  2017-02-24 16:12 ` [PATCH 04/29] xl: use <> variant to include Xen tools library headers Wei Liu
                   ` (25 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:12 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

There is no reason for a client to include a private header from libxl.
Remove the inclusion and define _GNU_SOURCE for {v,}asprintf in
xl_cmdimpl.c.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/xl.c         | 2 --
 tools/xl/xl_cmdimpl.c | 2 +-
 tools/xl/xl_sxp.c     | 2 --
 3 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/tools/xl/xl.c b/tools/xl/xl.c
index 4bc9648b71..5eab2c31c4 100644
--- a/tools/xl/xl.c
+++ b/tools/xl/xl.c
@@ -12,8 +12,6 @@
  * GNU Lesser General Public License for more details.
  */
 
-#include "libxl_osdeps.h"
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index a83739942c..4dfcbe61ca 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -12,7 +12,7 @@
  * GNU Lesser General Public License for more details.
  */
 
-#include "libxl_osdeps.h"
+#define _GNU_SOURCE
 
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/tools/xl/xl_sxp.c b/tools/xl/xl_sxp.c
index b67c0ae999..9ced6f17be 100644
--- a/tools/xl/xl_sxp.c
+++ b/tools/xl/xl_sxp.c
@@ -16,8 +16,6 @@
  * Legacy SXP output handling
  */
 
-#include "libxl_osdeps.h"
-
 #include <stdlib.h>
 #include <inttypes.h>
 
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 04/29] xl: use <> variant to include Xen tools library headers
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (2 preceding siblings ...)
  2017-02-24 16:12 ` [PATCH 03/29] xl: remove inclusion of libxl_osdeps.h Wei Liu
@ 2017-02-24 16:12 ` Wei Liu
  2017-02-27 15:54   ` Ian Jackson
  2017-02-24 16:12 ` [PATCH 05/29] xl: generate _paths.h Wei Liu
                   ` (24 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:12 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

They should be treated like any other libraries installed on the build
host. Compiler options are set correctly to point to their locations.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/xl.c          | 6 +++---
 tools/xl/xl.h          | 2 +-
 tools/xl/xl_cmdimpl.c  | 8 ++++----
 tools/xl/xl_cmdtable.c | 2 +-
 tools/xl/xl_sxp.c      | 4 ++--
 5 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/tools/xl/xl.c b/tools/xl/xl.c
index 5eab2c31c4..32346ad7a5 100644
--- a/tools/xl/xl.c
+++ b/tools/xl/xl.c
@@ -24,9 +24,9 @@
 #include <inttypes.h>
 #include <regex.h>
 
-#include "libxl.h"
-#include "libxl_utils.h"
-#include "libxlutil.h"
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
 #include "xl.h"
 
 xentoollog_logger_stdiostream *logger;
diff --git a/tools/xl/xl.h b/tools/xl/xl.h
index 84dd2a9265..a8b6264c59 100644
--- a/tools/xl/xl.h
+++ b/tools/xl/xl.h
@@ -18,7 +18,7 @@
 #include <assert.h>
 
 #include "_paths.h"
-#include "xentoollog.h"
+#include <xentoollog.h>
 
 struct cmd_spec {
     char *cmd_name;
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index 4dfcbe61ca..9901011008 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -34,10 +34,10 @@
 #include <limits.h>
 #include <xen/hvm/e820.h>
 
-#include "libxl.h"
-#include "libxl_utils.h"
-#include "libxl_json.h"
-#include "libxlutil.h"
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxl_json.h>
+#include <libxlutil.h>
 #include "xl.h"
 
 /* For calls which return an errno on failure */
diff --git a/tools/xl/xl_cmdtable.c b/tools/xl/xl_cmdtable.c
index ddcd6c2423..1219b3309d 100644
--- a/tools/xl/xl_cmdtable.c
+++ b/tools/xl/xl_cmdtable.c
@@ -14,7 +14,7 @@
 
 #include <string.h>
 
-#include "libxl.h"
+#include <libxl.h>
 #include "xl.h"
 
 struct cmd_spec cmd_table[] = {
diff --git a/tools/xl/xl_sxp.c b/tools/xl/xl_sxp.c
index 9ced6f17be..e738bf2465 100644
--- a/tools/xl/xl_sxp.c
+++ b/tools/xl/xl_sxp.c
@@ -19,8 +19,8 @@
 #include <stdlib.h>
 #include <inttypes.h>
 
-#include "libxl.h"
-#include "libxl_utils.h"
+#include <libxl.h>
+#include <libxl_utils.h>
 #include "xl.h"
 
 /* In general you should not add new output to this function since it
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 05/29] xl: generate _paths.h
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (3 preceding siblings ...)
  2017-02-24 16:12 ` [PATCH 04/29] xl: use <> variant to include Xen tools library headers Wei Liu
@ 2017-02-24 16:12 ` Wei Liu
  2017-02-27 15:54   ` Ian Jackson
  2017-02-24 16:12 ` [PATCH 06/29] xl: remove trailing spaces in xl_cmdimpl.c Wei Liu
                   ` (23 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:12 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

It is included by xl.h. Previously it was using _paths.h from some other
place. We'd better generate one for xl as well.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 .gitignore        | 1 +
 tools/xl/Makefile | 7 ++++++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore
index 557b38e1b2..3713b1e2a6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -380,6 +380,7 @@ tools/firmware/etherboot/ipxe/
 tools/python/xen/lowlevel/xl/_pyxl_types.c
 tools/python/xen/lowlevel/xl/_pyxl_types.h
 tools/xenstore/xenstore-watch
+tools/xl/_paths.h
 tools/xl/xl
 
 docs/txt/misc/*.txt
diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index 32dff40584..7106009d66 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -20,6 +20,11 @@ $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
 $(XL_OBJS): CFLAGS += -include $(XEN_ROOT)/tools/config.h # libxl_json.h needs it.
 
+genpath-target = $(call buildmakevars2header,_paths.h)
+$(eval $(genpath-target))
+
+$(XL_OBJS): _paths.h
+
 .PHONY: all
 all: xl
 
@@ -35,7 +40,7 @@ install: all
 
 .PHONY: clean
 clean:
-	$(RM) -f *.o xl $(DEPS)
+	$(RM) -f *.o xl _paths.h $(DEPS)
 
 distclean: clean
 
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 06/29] xl: remove trailing spaces in xl_cmdimpl.c
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (4 preceding siblings ...)
  2017-02-24 16:12 ` [PATCH 05/29] xl: generate _paths.h Wei Liu
@ 2017-02-24 16:12 ` Wei Liu
  2017-02-27 15:54   ` Ian Jackson
  2017-02-24 16:12 ` [PATCH 07/29] xl: lift a bunch of macros to xl_utils.h Wei Liu
                   ` (22 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:12 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/xl_cmdimpl.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index 9901011008..1d7cf8ffa8 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -6732,7 +6732,7 @@ static int sched_vcpu_output(libxl_scheduler sched,
     return 0;
 }
 
-/* 
+/*
  * <nothing>             : List all domain params and sched params from all pools
  * -d [domid]            : List domain params for domain
  * -d [domid] [params]   : Set domain params for domain
@@ -8374,7 +8374,7 @@ int main_cpupoolcreate(int argc, char **argv)
     }
     /* We made it! */
     rc = EXIT_SUCCESS;
-   
+
 out_cfg:
     xlu_cfg_destroy(config);
 out:
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 07/29] xl: lift a bunch of macros to xl_utils.h
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (5 preceding siblings ...)
  2017-02-24 16:12 ` [PATCH 06/29] xl: remove trailing spaces in xl_cmdimpl.c Wei Liu
@ 2017-02-24 16:12 ` Wei Liu
  2017-02-27 15:54   ` Ian Jackson
  2017-02-24 16:12 ` [PATCH 08/29] xl: move some helper functions to xl_utils.c Wei Liu
                   ` (21 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:12 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

We're going to split xl_cmdimpl.c into multiple files. Lift the commonly
used macros to xl_utils.h.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/xl_cmdimpl.c | 104 +---------------------------------------
 tools/xl/xl_utils.h   | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 130 insertions(+), 103 deletions(-)
 create mode 100644 tools/xl/xl_utils.h

diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index 1d7cf8ffa8..d9d947827d 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -39,42 +39,7 @@
 #include <libxl_json.h>
 #include <libxlutil.h>
 #include "xl.h"
-
-/* For calls which return an errno on failure */
-#define CHK_ERRNOVAL( call ) ({                                         \
-        int chk_errnoval = (call);                                      \
-        if (chk_errnoval < 0)                                           \
-            abort();                                                    \
-        else if (chk_errnoval > 0) {                                    \
-            fprintf(stderr,"xl: fatal error: %s:%d: %s: %s\n",          \
-                    __FILE__,__LINE__, strerror(chk_errnoval), #call);  \
-            exit(EXIT_FAILURE);                                         \
-        }                                                               \
-    })
-
-/* For calls which return -1 and set errno on failure */
-#define CHK_SYSCALL( call ) ({                                          \
-        if ((call) == -1) {                                             \
-            fprintf(stderr,"xl: fatal error: %s:%d: %s: %s\n",          \
-                    __FILE__,__LINE__, strerror(errno), #call);         \
-            exit(EXIT_FAILURE);                                         \
-        }                                                               \
-    })
-
-#define MUST( call ) ({                                                 \
-        int must_rc = (call);                                           \
-        if (must_rc < 0) {                                                  \
-            fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: %s\n",       \
-                    __FILE__,__LINE__, must_rc, #call);                 \
-            exit(EXIT_FAILURE);                                         \
-        }                                                               \
-    })
-
-#define STR_HAS_PREFIX( a, b )  \
-    ( strncmp(a, b, strlen(b)) == 0 )
-#define STR_SKIP_PREFIX( a, b ) \
-    ( STR_HAS_PREFIX(a, b) ? ((a) += strlen(b), 1) : 0 )
-
+#include "xl_utils.h"
 
 int logfile = 2;
 
@@ -83,7 +48,6 @@ libxl_ctx *ctx;
 
 xlchild children[child_max];
 
-#define INVALID_DOMID ~0
 static const char *common_domname;
 static int fd_lock = -1;
 
@@ -349,8 +313,6 @@ static char *xstrdup(const char *x)
 #define ARRAY_EXTEND_INIT_NODEVID(array,count,initfn) \
     ARRAY_EXTEND_INIT__CORE((array),(count),(initfn), /* nothing */ )
 
-#define LOG(_f, _a...)   dolog(__FILE__, __LINE__, __func__, _f "\n", ##_a)
-
 static void dolog(const char *file, int line, const char *func, char *fmt, ...)
      __attribute__((format(printf,4,5)));
 
@@ -3332,10 +3294,6 @@ static int64_t parse_mem_size_kb(const char *mem)
     return kbytes;
 }
 
-/* Must be last in list */
-#define COMMON_LONG_OPTS {"help", 0, 0, 'h'}, \
-                         {0, 0, 0, 0}
-
 /*
  * Callers should use SWITCH_FOREACH_OPT in preference to calling this
  * directly.
@@ -3378,66 +3336,6 @@ static int def_getopt(int argc, char * const argv[],
     return -1;
 }
 
-/*
- * Wraps def_getopt into a convenient loop+switch to process all
- * arguments. This macro is intended to be called from main_XXX().
- *
- *   SWITCH_FOREACH_OPT(int *opt, "OPTS",
- *                      const struct option *longopts,
- *                      const char *commandname,
- *                      int num_opts_req) { ...
- *
- * opt:               pointer to an int variable, holds the current option
- *                    during processing.
- * OPTS:              short options, as per getopt_long(3)'s optstring argument.
- *                    do not include "h"; will be provided automatically
- * longopts:          long options, as per getopt_long(3)'s longopts argument.
- *                    May be null.
- * commandname:       name of this command, for usage string.
- * num_required_opts: number of non-option command line parameters
- *                    which are required.
- *
- * In addition the calling context is expected to contain variables
- * "argc" and "argv" in the conventional C-style:
- *   main(int argc, char **argv)
- * manner.
- *
- * Callers should treat SWITCH_FOREACH_OPT as they would a switch
- * statement over the value of `opt`. Each option given in `opts` (or
- * `lopts`) should be handled by a case statement as if it were inside
- * a switch statement.
- *
- * In addition to the options provided in opts the macro will handle
- * the "help" option and enforce a minimum number of non-option
- * command line pearameters as follows:
- *  -- if the user passes a -h or --help option. help will be printed,
- *     and the macro will cause the process to exit with code 0.
- *  -- if the user does not provided `num_required_opts` non-option
- *     arguments, the macro will cause the process to exit with code 2.
- *
- * Example:
- *
- * int main_foo(int argc, char **argv) {
- *     int opt;
- *
- *     SWITCH_FOREACH_OPT(opt, "blah", NULL, "foo", 0) {
- *      case 'b':
- *          ... handle b option...
- *          break;
- *      case 'l':
- *          ... handle l option ...
- *          break;
- *      case etc etc...
- *      }
- *      ... do something useful with the options ...
- * }
- */
-#define SWITCH_FOREACH_OPT(opt, opts, longopts,                         \
-                           commandname, num_required_opts)              \
-    while (((opt) = def_getopt(argc, argv, "h" opts, (longopts),          \
-                                (commandname), (num_required_opts))) != -1) \
-        switch (opt)
-
 static int set_memory_max(uint32_t domid, const char *mem)
 {
     int64_t memorykb;
diff --git a/tools/xl/xl_utils.h b/tools/xl/xl_utils.h
new file mode 100644
index 0000000000..ebb9305b7c
--- /dev/null
+++ b/tools/xl/xl_utils.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#ifndef XL_UTILS_H
+#define XL_UTILS_H
+
+/* For calls which return an errno on failure */
+#define CHK_ERRNOVAL( call ) ({                                         \
+        int chk_errnoval = (call);                                      \
+        if (chk_errnoval < 0)                                           \
+            abort();                                                    \
+        else if (chk_errnoval > 0) {                                    \
+            fprintf(stderr,"xl: fatal error: %s:%d: %s: %s\n",          \
+                    __FILE__,__LINE__, strerror(chk_errnoval), #call);  \
+            exit(EXIT_FAILURE);                                         \
+        }                                                               \
+    })
+
+/* For calls which return -1 and set errno on failure */
+#define CHK_SYSCALL( call ) ({                                          \
+        if ((call) == -1) {                                             \
+            fprintf(stderr,"xl: fatal error: %s:%d: %s: %s\n",          \
+                    __FILE__,__LINE__, strerror(errno), #call);         \
+            exit(EXIT_FAILURE);                                         \
+        }                                                               \
+    })
+
+#define MUST( call ) ({                                                 \
+        int must_rc = (call);                                           \
+        if (must_rc < 0) {                                              \
+            fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: %s\n",       \
+                    __FILE__,__LINE__, must_rc, #call);                 \
+            exit(EXIT_FAILURE);                                         \
+        }                                                               \
+    })
+
+#define STR_HAS_PREFIX( a, b )  \
+    ( strncmp(a, b, strlen(b)) == 0 )
+#define STR_SKIP_PREFIX( a, b ) \
+    ( STR_HAS_PREFIX(a, b) ? ((a) += strlen(b), 1) : 0 )
+
+#define INVALID_DOMID ~0
+
+#define LOG(_f, _a...)   dolog(__FILE__, __LINE__, __func__, _f "\n", ##_a)
+
+/*
+ * Wraps def_getopt into a convenient loop+switch to process all
+ * arguments. This macro is intended to be called from main_XXX().
+ *
+ *   SWITCH_FOREACH_OPT(int *opt, "OPTS",
+ *                      const struct option *longopts,
+ *                      const char *commandname,
+ *                      int num_opts_req) { ...
+ *
+ * opt:               pointer to an int variable, holds the current option
+ *                    during processing.
+ * OPTS:              short options, as per getopt_long(3)'s optstring argument.
+ *                    do not include "h"; will be provided automatically
+ * longopts:          long options, as per getopt_long(3)'s longopts argument.
+ *                    May be null.
+ * commandname:       name of this command, for usage string.
+ * num_required_opts: number of non-option command line parameters
+ *                    which are required.
+ *
+ * In addition the calling context is expected to contain variables
+ * "argc" and "argv" in the conventional C-style:
+ *   main(int argc, char **argv)
+ * manner.
+ *
+ * Callers should treat SWITCH_FOREACH_OPT as they would a switch
+ * statement over the value of `opt`. Each option given in `opts` (or
+ * `lopts`) should be handled by a case statement as if it were inside
+ * a switch statement.
+ *
+ * In addition to the options provided in opts the macro will handle
+ * the "help" option and enforce a minimum number of non-option
+ * command line pearameters as follows:
+ *  -- if the user passes a -h or --help option. help will be printed,
+ *     and the macro will cause the process to exit with code 0.
+ *  -- if the user does not provided `num_required_opts` non-option
+ *     arguments, the macro will cause the process to exit with code 2.
+ *
+ * Example:
+ *
+ * int main_foo(int argc, char **argv) {
+ *     int opt;
+ *
+ *     SWITCH_FOREACH_OPT(opt, "blah", NULL, "foo", 0) {
+ *      case 'b':
+ *          ... handle b option...
+ *          break;
+ *      case 'l':
+ *          ... handle l option ...
+ *          break;
+ *      case etc etc...
+ *      }
+ *      ... do something useful with the options ...
+ * }
+ */
+#define SWITCH_FOREACH_OPT(opt, opts, longopts,                         \
+                           commandname, num_required_opts)              \
+    while (((opt) = def_getopt(argc, argv, "h" opts, (longopts),        \
+                               (commandname), (num_required_opts))) != -1) \
+        switch (opt)
+
+/* Must be last in list */
+#define COMMON_LONG_OPTS {"help", 0, 0, 'h'}, \
+                         {0, 0, 0, 0}
+
+#endif /* XL_UTILS_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 08/29] xl: move some helper functions to xl_utils.c
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (6 preceding siblings ...)
  2017-02-24 16:12 ` [PATCH 07/29] xl: lift a bunch of macros to xl_utils.h Wei Liu
@ 2017-02-24 16:12 ` Wei Liu
  2017-02-27 15:53   ` Ian Jackson
  2017-02-24 16:12 ` [PATCH 09/29] xl: split out tmem related code to xl_tmem.c Wei Liu
                   ` (20 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:12 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Move some commonly used functions to a new file. Prepend "x" to
function names to stick to consistent naming scheme.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   2 +-
 tools/xl/xl_cmdimpl.c | 343 +++++++++-----------------------------------------
 tools/xl/xl_utils.c   | 258 +++++++++++++++++++++++++++++++++++++
 tools/xl/xl_utils.h   |  33 ++++-
 4 files changed, 351 insertions(+), 285 deletions(-)
 create mode 100644 tools/xl/xl_utils.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index 7106009d66..2f740b4789 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -15,7 +15,7 @@ LDFLAGS += $(PTHREAD_LDFLAGS)
 CFLAGS_XL += $(CFLAGS_libxenlight)
 CFLAGS_XL += -Wshadow
 
-XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o
+XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
 $(XL_OBJS): CFLAGS += -include $(XEN_ROOT)/tools/config.h # libxl_json.h needs it.
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index d9d947827d..c45ffe943f 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -19,7 +19,6 @@
 #include <string.h>
 #include <unistd.h>
 #include <time.h>
-#include <getopt.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/time.h>
@@ -48,7 +47,7 @@ libxl_ctx *ctx;
 
 xlchild children[child_max];
 
-static const char *common_domname;
+const char *common_domname;
 static int fd_lock = -1;
 
 static const char savefileheader_magic[32]=
@@ -129,22 +128,6 @@ struct domain_create {
     char **migration_domname_r; /* from malloc */
 };
 
-
-static uint32_t find_domain(const char *p) __attribute__((warn_unused_result));
-static uint32_t find_domain(const char *p)
-{
-    uint32_t domid;
-    int rc;
-
-    rc = libxl_domain_qualifier_to_domid(ctx, p, &domid);
-    if (rc) {
-        fprintf(stderr, "%s is an invalid domain identifier (rc=%d)\n", p, rc);
-        exit(EXIT_FAILURE);
-    }
-    common_domname = libxl_domid_to_name(ctx, domid);
-    return domid;
-}
-
 int child_report(xlchildnum child)
 {
     int status;
@@ -253,47 +236,6 @@ release_lock:
     return rc;
 }
 
-static void *xmalloc(size_t sz) {
-    void *r;
-    r = malloc(sz);
-    if (!r) { fprintf(stderr,"xl: Unable to malloc %lu bytes.\n",
-                      (unsigned long)sz); exit(-ERROR_FAIL); }
-    return r;
-}
-
-static void *xcalloc(size_t n, size_t sz) __attribute__((unused));
-static void *xcalloc(size_t n, size_t sz) {
-    void *r = calloc(n, sz);
-    if (!r) {
-        fprintf(stderr,"xl: Unable to calloc %zu bytes.\n", sz*n);
-        exit(-ERROR_FAIL);
-    }
-    return r;
-}
-
-static void *xrealloc(void *ptr, size_t sz) {
-    void *r;
-    if (!sz) { free(ptr); return 0; }
-      /* realloc(non-0, 0) has a useless return value;
-       * but xrealloc(anything, 0) is like free
-       */
-    r = realloc(ptr, sz);
-    if (!r) { fprintf(stderr,"xl: Unable to realloc to %lu bytes.\n",
-                      (unsigned long)sz); exit(-ERROR_FAIL); }
-    return r;
-}
-
-static char *xstrdup(const char *x)
-{
-    char *r;
-    r = strdup(x);
-    if (!r) {
-        fprintf(stderr, "xl: Unable to strdup a string of length %zu.\n",
-                strlen(x));
-        exit(-ERROR_FAIL);
-    }
-    return r;
-}
 
 #define ARRAY_EXTEND_INIT__CORE(array,count,initfn,more)                \
     ({                                                                  \
@@ -313,46 +255,6 @@ static char *xstrdup(const char *x)
 #define ARRAY_EXTEND_INIT_NODEVID(array,count,initfn) \
     ARRAY_EXTEND_INIT__CORE((array),(count),(initfn), /* nothing */ )
 
-static void dolog(const char *file, int line, const char *func, char *fmt, ...)
-     __attribute__((format(printf,4,5)));
-
-static void dolog(const char *file, int line, const char *func, char *fmt, ...)
-{
-    va_list ap;
-    char *s = NULL;
-    int rc;
-
-    va_start(ap, fmt);
-    rc = vasprintf(&s, fmt, ap);
-    va_end(ap);
-    if (rc >= 0)
-        /* we ignore write errors since we have no way to report them;
-         * the alternative would be to abort the whole program */
-        libxl_write_exactly(NULL, logfile, s, rc, NULL, NULL);
-    free(s);
-}
-
-static void xvasprintf(char **strp, const char *fmt, va_list ap)
-    __attribute__((format(printf,2,0)));
-static void xvasprintf(char **strp, const char *fmt, va_list ap)
-{
-    int r = vasprintf(strp, fmt, ap);
-    if (r == -1) {
-        perror("asprintf failed");
-        exit(EXIT_FAILURE);
-    }
-}
-
-static void xasprintf(char **strp, const char *fmt, ...)
-    __attribute__((format(printf,2,3)));
-static void xasprintf(char **strp, const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    xvasprintf(strp, fmt, ap);
-    va_end(ap);
-}
-
 static yajl_gen_status printf_info_one_json(yajl_gen hand, int domid,
                                             libxl_domain_config *d_config)
 {
@@ -389,19 +291,6 @@ out:
     return s;
 }
 
-static void flush_stream(FILE *fh)
-{
-    const char *fh_name =
-        fh == stdout ? "stdout" :
-        fh == stderr ? "stderr" :
-        (abort(), (const char*)0);
-
-    if (ferror(fh) || fflush(fh)) {
-        perror(fh_name);
-        exit(EXIT_FAILURE);
-    }
-}
-
 static void printf_info(enum output_format output_format,
                         int domid,
                         libxl_domain_config *d_config, FILE *fh)
@@ -437,7 +326,7 @@ out:
         fprintf(stderr,
                 "unable to format domain config as JSON (YAJL:%d)\n", s);
 
-    flush_stream(fh);
+    xflush_stream(fh);
 }
 
 static int do_daemonize(char *name, const char *pidfile)
@@ -2942,7 +2831,7 @@ static int create_domain(struct domain_create *dom_info)
             }
             fputs(json, cfg_print_fh);
             free(json);
-            flush_stream(cfg_print_fh);
+            xflush_stream(cfg_print_fh);
         }
     }
 
@@ -3294,48 +3183,6 @@ static int64_t parse_mem_size_kb(const char *mem)
     return kbytes;
 }
 
-/*
- * Callers should use SWITCH_FOREACH_OPT in preference to calling this
- * directly.
- */
-static int def_getopt(int argc, char * const argv[],
-                      const char *optstring,
-                      const struct option *longopts,
-                      const char* helpstr, int reqargs)
-{
-    int opt;
-    const struct option def_options[] = {
-        COMMON_LONG_OPTS
-    };
-
-    if (!longopts)
-        longopts = def_options;
-
-    opterr = 0;
-    while ((opt = getopt_long(argc, argv, optstring, longopts, NULL)) == '?') {
-        if (optopt == 'h') {
-            help(helpstr);
-            exit(0);
-        }
-        fprintf(stderr, "option `%c' not supported.\n", optopt);
-        exit(2);
-    }
-    if (opt == 'h') {
-        help(helpstr);
-        exit(0);
-    }
-    if (opt != -1)
-        return opt;
-
-    if (argc - optind <= reqargs - 1) {
-        fprintf(stderr, "'xl %s' requires at least %d argument%s.\n\n",
-                helpstr, reqargs, reqargs > 1 ? "s" : "");
-        help(helpstr);
-        exit(2);
-    }
-    return -1;
-}
-
 static int set_memory_max(uint32_t domid, const char *mem)
 {
     int64_t memorykb;
@@ -3364,7 +3211,7 @@ int main_memmax(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     mem = argv[optind + 1];
 
     return set_memory_max(domid, mem);
@@ -3398,7 +3245,7 @@ int main_memset(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     mem = argv[optind + 1];
 
     return set_memory_target(domid, mem);
@@ -3454,7 +3301,7 @@ int main_cd_eject(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     virtdev = argv[optind + 1];
 
     if (cd_insert(domid, virtdev, NULL))
@@ -3474,7 +3321,7 @@ int main_cd_insert(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     virtdev = argv[optind + 1];
     file = argv[optind + 2];
 
@@ -3494,7 +3341,7 @@ int main_usbctrl_attach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind++]);
+    domid = xfind_domain(argv[optind++]);
 
     libxl_device_usbctrl_init(&usbctrl);
 
@@ -3523,7 +3370,7 @@ int main_usbctrl_detach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     devid = atoi(argv[optind+1]);
 
     libxl_device_usbctrl_init(&usbctrl);
@@ -3555,7 +3402,7 @@ int main_usbdev_attach(int argc, char **argv)
 
     libxl_device_usbdev_init(&usbdev);
 
-    domid = find_domain(argv[optind++]);
+    domid = xfind_domain(argv[optind++]);
 
     for (argv += optind, argc -= optind; argc > 0; ++argv, --argc) {
         if (parse_usbdev_config(&usbdev, *argv))
@@ -3583,7 +3430,7 @@ int main_usbdev_detach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     ctrl = atoi(argv[optind+1]);
     port = atoi(argv[optind+2]);
 
@@ -3620,7 +3467,7 @@ int main_usblist(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind++]);
+    domid = xfind_domain(argv[optind++]);
 
     if (argc > optind) {
         fprintf(stderr, "Invalid arguments.\n");
@@ -3696,7 +3543,7 @@ int main_console(int argc, char **argv)
         break;
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     if (!type)
         libxl_primary_console_exec(ctx, domid, -1);
     else
@@ -3721,7 +3568,7 @@ int main_vncviewer(int argc, char **argv)
         break;
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
 
     if (vncviewer(domid, autopass))
         return EXIT_FAILURE;
@@ -3755,7 +3602,7 @@ int main_pcilist(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
 
     pcilist(domid);
     return 0;
@@ -3803,7 +3650,7 @@ int main_pcidetach(int argc, char **argv)
         break;
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     bdf = argv[optind + 1];
 
     if (pcidetach(domid, bdf, force))
@@ -3847,7 +3694,7 @@ int main_pciattach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     bdf = argv[optind + 1];
 
     if (optind + 1 < argc)
@@ -4155,56 +4002,6 @@ out:
     }
 }
 
-static void print_bitmap(uint8_t *map, int maplen, FILE *stream)
-{
-    int i;
-    uint8_t pmap = 0, bitmask = 0;
-    int firstset = 0, state = 0;
-
-    for (i = 0; i < maplen; i++) {
-        if (i % 8 == 0) {
-            pmap = *map++;
-            bitmask = 1;
-        } else bitmask <<= 1;
-
-        switch (state) {
-        case 0:
-        case 2:
-            if ((pmap & bitmask) != 0) {
-                firstset = i;
-                state++;
-            }
-            continue;
-        case 1:
-        case 3:
-            if ((pmap & bitmask) == 0) {
-                fprintf(stream, "%s%d", state > 1 ? "," : "", firstset);
-                if (i - 1 > firstset)
-                    fprintf(stream, "-%d", i - 1);
-                state = 2;
-            }
-            continue;
-        }
-    }
-    switch (state) {
-        case 0:
-            fprintf(stream, "none");
-            break;
-        case 2:
-            break;
-        case 1:
-            if (firstset == 0) {
-                fprintf(stream, "all");
-                break;
-            }
-        case 3:
-            fprintf(stream, "%s%d", state > 1 ? "," : "", firstset);
-            if (i - 1 > firstset)
-                fprintf(stream, "-%d", i - 1);
-            break;
-    }
-}
-
 static void list_domains(bool verbose, bool context, bool claim, bool numa,
                          bool cpupool, const libxl_dominfo *info, int nb_domain)
 {
@@ -5023,7 +4820,7 @@ int main_save(int argc, char **argv)
         return EXIT_FAILURE;
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     filename = argv[optind + 1];
     if ( argc - optind >= 3 )
         config_filename = argv[optind + 2];
@@ -5071,7 +4868,7 @@ int main_migrate(int argc, char **argv)
         break;
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     host = argv[optind + 1];
 
     bool pass_tty_arg = progress_use_cr || (isatty(2) > 0);
@@ -5112,7 +4909,7 @@ int main_dump_core(int argc, char **argv)
         /* No options */
     }
 
-    core_dump_domain(find_domain(argv[optind]), argv[optind + 1]);
+    core_dump_domain(xfind_domain(argv[optind]), argv[optind + 1]);
     return EXIT_SUCCESS;
 }
 
@@ -5124,7 +4921,7 @@ int main_pause(int argc, char **argv)
         /* No options */
     }
 
-    pause_domain(find_domain(argv[optind]));
+    pause_domain(xfind_domain(argv[optind]));
 
     return EXIT_SUCCESS;
 }
@@ -5137,7 +4934,7 @@ int main_unpause(int argc, char **argv)
         /* No options */
     }
 
-    unpause_domain(find_domain(argv[optind]));
+    unpause_domain(xfind_domain(argv[optind]));
 
     return EXIT_SUCCESS;
 }
@@ -5153,7 +4950,7 @@ int main_destroy(int argc, char **argv)
         break;
     }
 
-    destroy_domain(find_domain(argv[optind]), force);
+    destroy_domain(xfind_domain(argv[optind]), force);
     return EXIT_SUCCESS;
 }
 
@@ -5216,7 +5013,7 @@ static int main_shutdown_or_reboot(int do_reboot, int argc, char **argv)
         libxl_dominfo_list_free(dominfo, nb_domain);
     } else {
         libxl_evgen_domain_death *deathw = NULL;
-        uint32_t domid = find_domain(argv[optind]);
+        uint32_t domid = xfind_domain(argv[optind]);
 
         fn(domid, wait_for_it ? &deathw : NULL, 0, fallback_trigger);
 
@@ -5287,7 +5084,7 @@ int main_list(int argc, char **argv)
         }
         info_free = info;
     } else if (optind == argc-1) {
-        uint32_t domid = find_domain(argv[optind]);
+        uint32_t domid = xfind_domain(argv[optind]);
         rc = libxl_domain_info(ctx, &info_buf, domid);
         if (rc == ERROR_DOMAIN_NOTFOUND) {
             fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
@@ -5331,22 +5128,6 @@ int main_vm_list(int argc, char **argv)
     return EXIT_SUCCESS;
 }
 
-static void string_realloc_append(char **accumulate, const char *more)
-{
-    /* Appends more to accumulate.  Accumulate is either NULL, or
-     * points (always) to a malloc'd nul-terminated string. */
-
-    size_t oldlen = *accumulate ? strlen(*accumulate) : 0;
-    size_t morelen = strlen(more) + 1/*nul*/;
-    if (oldlen > SSIZE_MAX || morelen > SSIZE_MAX - oldlen) {
-        fprintf(stderr,"Additional config data far too large\n");
-        exit(-ERROR_FAIL);
-    }
-
-    *accumulate = xrealloc(*accumulate, oldlen + morelen);
-    memcpy(*accumulate + oldlen, more, morelen);
-}
-
 int main_create(int argc, char **argv)
 {
     const char *filename = NULL;
@@ -5408,8 +5189,8 @@ int main_create(int argc, char **argv)
 
     for (; optind < argc; optind++) {
         if (strchr(argv[optind], '=') != NULL) {
-            string_realloc_append(&dom_info.extra_config, argv[optind]);
-            string_realloc_append(&dom_info.extra_config, "\n");
+            xstring_realloc_append(&dom_info.extra_config, argv[optind]);
+            xstring_realloc_append(&dom_info.extra_config, "\n");
         } else if (!filename) {
             filename = argv[optind];
         } else {
@@ -5466,7 +5247,7 @@ int main_config_update(int argc, char **argv)
     fprintf(stderr, "WARNING: xl now has better capability to manage domain configuration, "
             "avoid using this command when possible\n");
 
-    domid = find_domain(argv[1]);
+    domid = xfind_domain(argv[1]);
     argc--; argv++;
 
     if (argv[1] && argv[1][0] != '-' && !strchr(argv[1], '=')) {
@@ -5485,8 +5266,8 @@ int main_config_update(int argc, char **argv)
 
     for (; optind < argc; optind++) {
         if (strchr(argv[optind], '=') != NULL) {
-            string_realloc_append(&extra_config, argv[optind]);
-            string_realloc_append(&extra_config, "\n");
+            xstring_realloc_append(&extra_config, argv[optind]);
+            xstring_realloc_append(&extra_config, "\n");
         } else if (!filename) {
             filename = argv[optind];
         } else {
@@ -5574,7 +5355,7 @@ int main_button_press(int argc, char **argv)
         /* No options */
     }
 
-    button_press(find_domain(argv[optind]), argv[optind + 1]);
+    button_press(xfind_domain(argv[optind]), argv[optind + 1]);
 
     return 0;
 }
@@ -5651,7 +5432,7 @@ static void vcpulist(int argc, char **argv)
         libxl_dominfo_list_free(dominfo, nb_domain);
     } else {
         for (; argc > 0; ++argv, --argc) {
-            uint32_t domid = find_domain(*argv);
+            uint32_t domid = xfind_domain(*argv);
             print_domain_vcpuinfo(domid, physinfo.nr_cpus);
         }
     }
@@ -5702,7 +5483,7 @@ int main_vcpupin(int argc, char **argv)
         break;
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     vcpu = argv[optind+1];
     hard_str = argv[optind+2];
     soft_str = (argc > optind+3) ? argv[optind+3] : NULL;
@@ -5879,7 +5660,7 @@ int main_vcpuset(int argc, char **argv)
         break;
     }
 
-    if (vcpuset(find_domain(argv[optind]), argv[optind + 1], check_host))
+    if (vcpuset(xfind_domain(argv[optind]), argv[optind + 1], check_host))
         return EXIT_FAILURE;
 
     return EXIT_SUCCESS;
@@ -6176,7 +5957,7 @@ int main_sharing(int argc, char **argv)
         }
         info_free = info;
     } else if (optind == argc-1) {
-        uint32_t domid = find_domain(argv[optind]);
+        uint32_t domid = xfind_domain(argv[optind]);
         rc = libxl_domain_info(ctx, &info_buf, domid);
         if (rc == ERROR_DOMAIN_NOTFOUND) {
             fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
@@ -6741,7 +6522,7 @@ int main_sched_credit(int argc, char **argv)
                                 cpupool))
             return EXIT_FAILURE;
     } else {
-        uint32_t domid = find_domain(dom);
+        uint32_t domid = xfind_domain(dom);
 
         if (!opt_w && !opt_c) { /* output credit scheduler info */
             sched_credit_domain_output(-1);
@@ -6842,7 +6623,7 @@ int main_sched_credit2(int argc, char **argv)
                                 cpupool))
             return EXIT_FAILURE;
     } else {
-        uint32_t domid = find_domain(dom);
+        uint32_t domid = xfind_domain(dom);
 
         if (!opt_w) { /* output credit2 scheduler info */
             sched_credit2_domain_output(-1);
@@ -6993,7 +6774,7 @@ int main_sched_rtds(int argc, char **argv)
             goto out;
         }
     } else {
-        uint32_t domid = find_domain(dom);
+        uint32_t domid = xfind_domain(dom);
         if (!opt_v && !opt_all) { /* output default scheduling parameters */
             sched_rtds_domain_output(-1);
             rc = -sched_rtds_domain_output(domid);
@@ -7125,7 +6906,7 @@ int main_rename(int argc, char **argv)
     dom = argv[optind++];
     new_name = argv[optind];
 
-    domid = find_domain(dom);
+    domid = xfind_domain(dom);
     if (libxl_domain_rename(ctx, domid, common_domname, new_name)) {
         fprintf(stderr, "Can't rename domain '%s'.\n", dom);
         return 1;
@@ -7147,7 +6928,7 @@ int main_trigger(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind++]);
+    domid = xfind_domain(argv[optind++]);
 
     trigger_name = argv[optind++];
     if (libxl_trigger_from_string(trigger_name, &trigger)) {
@@ -7178,7 +6959,7 @@ int main_sysrq(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind++]);
+    domid = xfind_domain(argv[optind++]);
 
     sysrq = argv[optind];
 
@@ -7260,7 +7041,7 @@ int main_networkattach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
 
     config= xlu_cfg_init(stderr, "command line");
     if (!config) {
@@ -7309,7 +7090,7 @@ int main_networklist(int argc, char **argv)
     printf("%-3s %-2s %-17s %-6s %-5s %-6s %5s/%-5s %-30s\n",
            "Idx", "BE", "Mac Addr.", "handle", "state", "evt-ch", "tx-", "rx-ring-ref", "BE-path");
     for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
-        uint32_t domid = find_domain(*argv);
+        uint32_t domid = xfind_domain(*argv);
         nics = libxl_device_nic_list(ctx, domid, &nb);
         if (!nics) {
             continue;
@@ -7343,7 +7124,7 @@ int main_networkdetach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
 
     if (!strchr(argv[optind+1], ':')) {
         if (libxl_devid_to_device_nic(ctx, domid, atoi(argv[optind+1]), &nic)) {
@@ -7379,7 +7160,7 @@ int main_channellist(int argc, char **argv)
     printf("%-3s %-2s %-5s %-6s %8s %-10s %-30s\n",
            "Idx", "BE", "state", "evt-ch", "ring-ref", "connection", "");
     for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
-        uint32_t domid = find_domain(*argv);
+        uint32_t domid = xfind_domain(*argv);
         channels = libxl_device_channel_list(ctx, domid, &nb);
         if (!channels)
             continue;
@@ -7491,7 +7272,7 @@ int main_blockdetach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
 
     if (libxl_vdev_to_device_disk(ctx, domid, argv[optind+1], &disk)) {
         fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]);
@@ -7607,7 +7388,7 @@ int main_vtpmdetach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
 
     if ( libxl_uuid_from_string(&uuid, argv[optind+1])) {
         if (libxl_devid_to_device_vtpm(ctx, domid, atoi(argv[optind+1]), &vtpm)) {
@@ -7836,7 +7617,7 @@ int main_uptime(int argc, char **argv)
     }
 
     for (;(dom = argv[optind]) != NULL; nb_doms++,optind++)
-        domains[nb_doms] = find_domain(dom);
+        domains[nb_doms] = xfind_domain(dom);
 
     print_uptime(short_mode, domains, nb_doms);
 
@@ -7871,7 +7652,7 @@ int main_tmem_list(int argc, char **argv)
     if (all)
         domid = INVALID_DOMID;
     else
-        domid = find_domain(dom);
+        domid = xfind_domain(dom);
 
     buf = libxl_tmem_list(ctx, domid, use_long);
     if (buf == NULL)
@@ -7905,7 +7686,7 @@ int main_tmem_freeze(int argc, char **argv)
     if (all)
         domid = INVALID_DOMID;
     else
-        domid = find_domain(dom);
+        domid = xfind_domain(dom);
 
     if (libxl_tmem_freeze(ctx, domid) < 0)
         return EXIT_FAILURE;
@@ -7936,7 +7717,7 @@ int main_tmem_thaw(int argc, char **argv)
     if (all)
         domid = INVALID_DOMID;
     else
-        domid = find_domain(dom);
+        domid = xfind_domain(dom);
 
     if (libxl_tmem_thaw(ctx, domid) < 0)
         return EXIT_FAILURE;
@@ -7982,7 +7763,7 @@ int main_tmem_set(int argc, char **argv)
     if (all)
         domid = INVALID_DOMID;
     else
-        domid = find_domain(dom);
+        domid = xfind_domain(dom);
 
     if (!opt_w && !opt_c && !opt_p) {
         fprintf(stderr, "No set value specified.\n\n");
@@ -8036,7 +7817,7 @@ int main_tmem_shared_auth(int argc, char **argv)
     if (all)
         domid = INVALID_DOMID;
     else
-        domid = find_domain(dom);
+        domid = xfind_domain(dom);
 
     if (uuid == NULL || autharg == NULL) {
         fprintf(stderr, "No uuid or auth specified.\n\n");
@@ -8115,8 +7896,8 @@ int main_cpupoolcreate(int argc, char **argv)
 
     while (optind < argc) {
         if ((p = strchr(argv[optind], '='))) {
-            string_realloc_append(&extra_config, "\n");
-            string_realloc_append(&extra_config, argv[optind]);
+            xstring_realloc_append(&extra_config, "\n");
+            xstring_realloc_append(&extra_config, argv[optind]);
         } else if (!filename) {
             filename = argv[optind];
         } else {
@@ -8830,7 +8611,7 @@ int main_remus(int argc, char **argv)
         libxl_defbool_set(&r_info.colo, true);
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     host = argv[optind + 1];
 
     /* Defaults */
@@ -9179,7 +8960,7 @@ int main_psr_cmt_attach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     ret = libxl_psr_cmt_attach(ctx, domid);
 
     return ret;
@@ -9194,7 +8975,7 @@ int main_psr_cmt_detach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     ret = libxl_psr_cmt_detach(ctx, domid);
 
     return ret;
@@ -9224,7 +9005,7 @@ int main_psr_cmt_show(int argc, char **argv)
     if (optind + 1 >= argc)
         domid = INVALID_DOMID;
     else if (optind + 1 == argc - 1)
-        domid = find_domain(argv[optind + 1]);
+        domid = xfind_domain(argv[optind + 1]);
     else {
         help("psr-cmt-show");
         return 2;
@@ -9440,7 +9221,7 @@ int main_psr_cat_cbm_set(int argc, char **argv)
         return 2;
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     cbm = strtoll(argv[optind + 1], NULL , 0);
 
     ret = libxl_psr_cat_set_cbm(ctx, domid, type, &target_map, cbm);
@@ -9461,7 +9242,7 @@ int main_psr_cat_show(int argc, char **argv)
     if (optind >= argc)
         domid = INVALID_DOMID;
     else if (optind == argc - 1)
-        domid = find_domain(argv[optind]);
+        domid = xfind_domain(argv[optind]);
     else {
         help("psr-cat-show");
         return 2;
@@ -9512,7 +9293,7 @@ int main_qemu_monitor_command(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     cmd = argv[optind + 1];
 
     if (argc - optind > 2) {
diff --git a/tools/xl/xl_utils.c b/tools/xl/xl_utils.c
new file mode 100644
index 0000000000..e0b4cb2547
--- /dev/null
+++ b/tools/xl/xl_utils.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#define _GNU_SOURCE
+
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+
+extern int logfile;
+extern const char *common_domname;
+
+void dolog(const char *file, int line, const char *func, char *fmt, ...)
+{
+    va_list ap;
+    char *s = NULL;
+    int rc;
+
+    va_start(ap, fmt);
+    rc = vasprintf(&s, fmt, ap);
+    va_end(ap);
+    if (rc >= 0)
+        /* we ignore write errors since we have no way to report them;
+         * the alternative would be to abort the whole program */
+        libxl_write_exactly(NULL, logfile, s, rc, NULL, NULL);
+    free(s);
+}
+
+void xvasprintf(char **strp, const char *fmt, va_list ap)
+{
+    int r = vasprintf(strp, fmt, ap);
+    if (r == -1) {
+        perror("asprintf failed");
+        exit(EXIT_FAILURE);
+    }
+}
+
+void xasprintf(char **strp, const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    xvasprintf(strp, fmt, ap);
+    va_end(ap);
+}
+
+void *xmalloc(size_t sz)
+{
+    void *r;
+    r = malloc(sz);
+    if (!r) {
+        fprintf(stderr,"xl: Unable to malloc %lu bytes.\n",
+                (unsigned long)sz);
+        exit(-ERROR_FAIL);
+    }
+    return r;
+}
+
+void *xcalloc(size_t n, size_t sz)
+{
+    void *r = calloc(n, sz);
+    if (!r) {
+        fprintf(stderr,"xl: Unable to calloc %zu bytes.\n", sz*n);
+        exit(-ERROR_FAIL);
+    }
+    return r;
+}
+
+void *xrealloc(void *ptr, size_t sz)
+{
+    void *r;
+    if (!sz) {
+        free(ptr);
+        return 0;
+    }
+    /* realloc(non-0, 0) has a useless return value;
+     * but xrealloc(anything, 0) is like free
+     */
+    r = realloc(ptr, sz);
+    if (!r) {
+        fprintf(stderr,"xl: Unable to realloc to %lu bytes.\n",
+                (unsigned long)sz);
+        exit(-ERROR_FAIL);
+    }
+    return r;
+}
+
+char *xstrdup(const char *x)
+{
+    char *r;
+    r = strdup(x);
+    if (!r) {
+        fprintf(stderr, "xl: Unable to strdup a string of length %zu.\n",
+                strlen(x));
+        exit(-ERROR_FAIL);
+    }
+    return r;
+}
+
+void xflush_stream(FILE *fh)
+{
+    const char *fh_name =
+        fh == stdout ? "stdout" :
+        fh == stderr ? "stderr" :
+        (abort(), (const char*)0);
+
+    if (ferror(fh) || fflush(fh)) {
+        perror(fh_name);
+        exit(EXIT_FAILURE);
+    }
+}
+
+uint32_t xfind_domain(const char *p)
+{
+    uint32_t domid;
+    int rc;
+
+    rc = libxl_domain_qualifier_to_domid(ctx, p, &domid);
+    if (rc) {
+        fprintf(stderr, "%s is an invalid domain identifier (rc=%d)\n", p, rc);
+        exit(EXIT_FAILURE);
+    }
+    common_domname = libxl_domid_to_name(ctx, domid);
+    return domid;
+}
+
+/*
+ * Callers should use SWITCH_FOREACH_OPT in preference to calling this
+ * directly.
+ */
+int xdef_getopt(int argc, char * const argv[],
+                const char *optstring,
+                const struct option *longopts,
+                const char* helpstr, int reqargs)
+{
+    int opt;
+    const struct option def_options[] = {
+        COMMON_LONG_OPTS
+    };
+
+    if (!longopts)
+        longopts = def_options;
+
+    opterr = 0;
+    while ((opt = getopt_long(argc, argv, optstring, longopts, NULL)) == '?') {
+        if (optopt == 'h') {
+            help(helpstr);
+            exit(0);
+        }
+        fprintf(stderr, "option `%c' not supported.\n", optopt);
+        exit(2);
+    }
+    if (opt == 'h') {
+        help(helpstr);
+        exit(0);
+    }
+    if (opt != -1)
+        return opt;
+
+    if (argc - optind <= reqargs - 1) {
+        fprintf(stderr, "'xl %s' requires at least %d argument%s.\n\n",
+                helpstr, reqargs, reqargs > 1 ? "s" : "");
+        help(helpstr);
+        exit(2);
+    }
+    return -1;
+}
+
+void xstring_realloc_append(char **accumulate, const char *more)
+{
+    /* Appends more to accumulate.  Accumulate is either NULL, or
+     * points (always) to a malloc'd nul-terminated string. */
+
+    size_t oldlen = *accumulate ? strlen(*accumulate) : 0;
+    size_t morelen = strlen(more) + 1/*nul*/;
+    if (oldlen > SSIZE_MAX || morelen > SSIZE_MAX - oldlen) {
+        fprintf(stderr,"Additional config data far too large\n");
+        exit(-ERROR_FAIL);
+    }
+
+    *accumulate = xrealloc(*accumulate, oldlen + morelen);
+    memcpy(*accumulate + oldlen, more, morelen);
+}
+
+void print_bitmap(uint8_t *map, int maplen, FILE *stream)
+{
+    int i;
+    uint8_t pmap = 0, bitmask = 0;
+    int firstset = 0, state = 0;
+
+    for (i = 0; i < maplen; i++) {
+        if (i % 8 == 0) {
+            pmap = *map++;
+            bitmask = 1;
+        } else bitmask <<= 1;
+
+        switch (state) {
+        case 0:
+        case 2:
+            if ((pmap & bitmask) != 0) {
+                firstset = i;
+                state++;
+            }
+            continue;
+        case 1:
+        case 3:
+            if ((pmap & bitmask) == 0) {
+                fprintf(stream, "%s%d", state > 1 ? "," : "", firstset);
+                if (i - 1 > firstset)
+                    fprintf(stream, "-%d", i - 1);
+                state = 2;
+            }
+            continue;
+        }
+    }
+    switch (state) {
+        case 0:
+            fprintf(stream, "none");
+            break;
+        case 2:
+            break;
+        case 1:
+            if (firstset == 0) {
+                fprintf(stream, "all");
+                break;
+            }
+        case 3:
+            fprintf(stream, "%s%d", state > 1 ? "," : "", firstset);
+            if (i - 1 > firstset)
+                fprintf(stream, "-%d", i - 1);
+            break;
+    }
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/xl/xl_utils.h b/tools/xl/xl_utils.h
index ebb9305b7c..2786f7c3cd 100644
--- a/tools/xl/xl_utils.h
+++ b/tools/xl/xl_utils.h
@@ -15,6 +15,8 @@
 #ifndef XL_UTILS_H
 #define XL_UTILS_H
 
+#include <getopt.h>
+
 /* For calls which return an errno on failure */
 #define CHK_ERRNOVAL( call ) ({                                         \
         int chk_errnoval = (call);                                      \
@@ -55,7 +57,7 @@
 #define LOG(_f, _a...)   dolog(__FILE__, __LINE__, __func__, _f "\n", ##_a)
 
 /*
- * Wraps def_getopt into a convenient loop+switch to process all
+ * Wraps xdef_getopt into a convenient loop+switch to process all
  * arguments. This macro is intended to be called from main_XXX().
  *
  *   SWITCH_FOREACH_OPT(int *opt, "OPTS",
@@ -110,14 +112,39 @@
  */
 #define SWITCH_FOREACH_OPT(opt, opts, longopts,                         \
                            commandname, num_required_opts)              \
-    while (((opt) = def_getopt(argc, argv, "h" opts, (longopts),        \
-                               (commandname), (num_required_opts))) != -1) \
+    while (((opt) = xdef_getopt(argc, argv, "h" opts, (longopts),       \
+                                (commandname), (num_required_opts))) != -1) \
         switch (opt)
 
 /* Must be last in list */
 #define COMMON_LONG_OPTS {"help", 0, 0, 'h'}, \
                          {0, 0, 0, 0}
 
+int xdef_getopt(int argc, char * const argv[],
+                const char *optstring,
+                const struct option *longopts,
+                const char* helpstr, int reqargs);
+
+void dolog(const char *file, int line, const char *func, char *fmt, ...)
+	__attribute__((format(printf,4,5)));
+
+void xvasprintf(char **strp, const char *fmt, va_list ap)
+	__attribute__((format(printf,2,0)));
+
+void xasprintf(char **strp, const char *fmt, ...)
+	__attribute__((format(printf,2,3)));
+
+void *xmalloc(size_t sz);
+void *xcalloc(size_t n, size_t sz);
+void *xrealloc(void *ptr, size_t sz);
+char *xstrdup(const char *x);
+void xstring_realloc_append(char **accumulate, const char *more);
+
+void xflush_stream(FILE *fh);
+uint32_t xfind_domain(const char *p) __attribute__((warn_unused_result));
+
+void print_bitmap(uint8_t *map, int maplen, FILE *stream);
+
 #endif /* XL_UTILS_H */
 
 /*
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 09/29] xl: split out tmem related code to xl_tmem.c
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (7 preceding siblings ...)
  2017-02-24 16:12 ` [PATCH 08/29] xl: move some helper functions to xl_utils.c Wei Liu
@ 2017-02-24 16:12 ` Wei Liu
  2017-02-27 15:54   ` Ian Jackson
  2017-02-24 16:12 ` [PATCH 10/29] xl: split out xl_parse.[ch] Wei Liu
                   ` (19 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:12 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   2 +
 tools/xl/xl_cmdimpl.c | 229 ---------------------------------------------
 tools/xl/xl_tmem.c    | 251 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 253 insertions(+), 229 deletions(-)
 create mode 100644 tools/xl/xl_tmem.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index 2f740b4789..f5df366e0a 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -16,6 +16,8 @@ CFLAGS_XL += $(CFLAGS_libxenlight)
 CFLAGS_XL += -Wshadow
 
 XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
+XL_OBJS += xl_tmem.o
+
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
 $(XL_OBJS): CFLAGS += -include $(XEN_ROOT)/tools/config.h # libxl_json.h needs it.
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index c45ffe943f..3c037eb2ec 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -7624,235 +7624,6 @@ int main_uptime(int argc, char **argv)
     return 0;
 }
 
-int main_tmem_list(int argc, char **argv)
-{
-    uint32_t domid;
-    const char *dom = NULL;
-    char *buf = NULL;
-    int use_long = 0;
-    int all = 0;
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "al", NULL, "tmem-list", 0) {
-    case 'l':
-        use_long = 1;
-        break;
-    case 'a':
-        all = 1;
-        break;
-    }
-
-    dom = argv[optind];
-    if (!dom && all == 0) {
-        fprintf(stderr, "You must specify -a or a domain id.\n\n");
-        help("tmem-list");
-        return 1;
-    }
-
-    if (all)
-        domid = INVALID_DOMID;
-    else
-        domid = xfind_domain(dom);
-
-    buf = libxl_tmem_list(ctx, domid, use_long);
-    if (buf == NULL)
-        return EXIT_FAILURE;
-
-    printf("%s\n", buf);
-    free(buf);
-    return EXIT_SUCCESS;
-}
-
-int main_tmem_freeze(int argc, char **argv)
-{
-    uint32_t domid;
-    const char *dom = NULL;
-    int all = 0;
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "a", NULL, "tmem-freeze", 0) {
-    case 'a':
-        all = 1;
-        break;
-    }
-
-    dom = argv[optind];
-    if (!dom && all == 0) {
-        fprintf(stderr, "You must specify -a or a domain id.\n\n");
-        help("tmem-freeze");
-        return EXIT_FAILURE;
-    }
-
-    if (all)
-        domid = INVALID_DOMID;
-    else
-        domid = xfind_domain(dom);
-
-    if (libxl_tmem_freeze(ctx, domid) < 0)
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-int main_tmem_thaw(int argc, char **argv)
-{
-    uint32_t domid;
-    const char *dom = NULL;
-    int all = 0;
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "a", NULL, "tmem-thaw", 0) {
-    case 'a':
-        all = 1;
-        break;
-    }
-
-    dom = argv[optind];
-    if (!dom && all == 0) {
-        fprintf(stderr, "You must specify -a or a domain id.\n\n");
-        help("tmem-thaw");
-        return EXIT_FAILURE;
-    }
-
-    if (all)
-        domid = INVALID_DOMID;
-    else
-        domid = xfind_domain(dom);
-
-    if (libxl_tmem_thaw(ctx, domid) < 0)
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-int main_tmem_set(int argc, char **argv)
-{
-    uint32_t domid;
-    const char *dom = NULL;
-    uint32_t weight = 0, cap = 0, compress = 0;
-    int opt_w = 0, opt_c = 0, opt_p = 0;
-    int all = 0;
-    int opt;
-    int rc = 0;
-
-    SWITCH_FOREACH_OPT(opt, "aw:c:p:", NULL, "tmem-set", 0) {
-    case 'a':
-        all = 1;
-        break;
-    case 'w':
-        weight = strtol(optarg, NULL, 10);
-        opt_w = 1;
-        break;
-    case 'c':
-        cap = strtol(optarg, NULL, 10);
-        opt_c = 1;
-        break;
-    case 'p':
-        compress = strtol(optarg, NULL, 10);
-        opt_p = 1;
-        break;
-    }
-
-    dom = argv[optind];
-    if (!dom && all == 0) {
-        fprintf(stderr, "You must specify -a or a domain id.\n\n");
-        help("tmem-set");
-        return EXIT_FAILURE;
-    }
-
-    if (all)
-        domid = INVALID_DOMID;
-    else
-        domid = xfind_domain(dom);
-
-    if (!opt_w && !opt_c && !opt_p) {
-        fprintf(stderr, "No set value specified.\n\n");
-        help("tmem-set");
-        return EXIT_FAILURE;
-    }
-
-    if (opt_w)
-        rc = libxl_tmem_set(ctx, domid, "weight", weight);
-    if (opt_c)
-        rc = libxl_tmem_set(ctx, domid, "cap", cap);
-    if (opt_p)
-        rc = libxl_tmem_set(ctx, domid, "compress", compress);
-
-    if (rc < 0)
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-int main_tmem_shared_auth(int argc, char **argv)
-{
-    uint32_t domid;
-    const char *autharg = NULL;
-    char *endptr = NULL;
-    const char *dom = NULL;
-    char *uuid = NULL;
-    int auth = -1;
-    int all = 0;
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "au:A:", NULL, "tmem-shared-auth", 0) {
-    case 'a':
-        all = 1;
-        break;
-    case 'u':
-        uuid = optarg;
-        break;
-    case 'A':
-        autharg = optarg;
-        break;
-    }
-
-    dom = argv[optind];
-    if (!dom && all == 0) {
-        fprintf(stderr, "You must specify -a or a domain id.\n\n");
-        help("tmem-shared-auth");
-        return EXIT_FAILURE;
-    }
-
-    if (all)
-        domid = INVALID_DOMID;
-    else
-        domid = xfind_domain(dom);
-
-    if (uuid == NULL || autharg == NULL) {
-        fprintf(stderr, "No uuid or auth specified.\n\n");
-        help("tmem-shared-auth");
-        return EXIT_FAILURE;
-    }
-
-    auth = strtol(autharg, &endptr, 10);
-    if (*endptr != '\0') {
-        fprintf(stderr, "Invalid auth, valid auth are <0|1>.\n\n");
-        return EXIT_FAILURE;
-    }
-
-    if (libxl_tmem_shared_auth(ctx, domid, uuid, auth) < 0)
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-int main_tmem_freeable(int argc, char **argv)
-{
-    int opt;
-    int mb;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "tmem-freeable", 0) {
-        /* No options */
-    }
-
-    mb = libxl_tmem_freeable(ctx);
-    if (mb == -1)
-        return EXIT_FAILURE;
-
-    printf("%d\n", mb);
-    return EXIT_SUCCESS;
-}
 
 int main_cpupoolcreate(int argc, char **argv)
 {
diff --git a/tools/xl/xl_tmem.c b/tools/xl/xl_tmem.c
new file mode 100644
index 0000000000..9d3570d404
--- /dev/null
+++ b/tools/xl/xl_tmem.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <libxl.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+
+int main_tmem_list(int argc, char **argv)
+{
+    uint32_t domid;
+    const char *dom = NULL;
+    char *buf = NULL;
+    int use_long = 0;
+    int all = 0;
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "al", NULL, "tmem-list", 0) {
+    case 'l':
+        use_long = 1;
+        break;
+    case 'a':
+        all = 1;
+        break;
+    }
+
+    dom = argv[optind];
+    if (!dom && all == 0) {
+        fprintf(stderr, "You must specify -a or a domain id.\n\n");
+        help("tmem-list");
+        return 1;
+    }
+
+    if (all)
+        domid = INVALID_DOMID;
+    else
+        domid = xfind_domain(dom);
+
+    buf = libxl_tmem_list(ctx, domid, use_long);
+    if (buf == NULL)
+        return EXIT_FAILURE;
+
+    printf("%s\n", buf);
+    free(buf);
+    return EXIT_SUCCESS;
+}
+
+int main_tmem_freeze(int argc, char **argv)
+{
+    uint32_t domid;
+    const char *dom = NULL;
+    int all = 0;
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "a", NULL, "tmem-freeze", 0) {
+    case 'a':
+        all = 1;
+        break;
+    }
+
+    dom = argv[optind];
+    if (!dom && all == 0) {
+        fprintf(stderr, "You must specify -a or a domain id.\n\n");
+        help("tmem-freeze");
+        return EXIT_FAILURE;
+    }
+
+    if (all)
+        domid = INVALID_DOMID;
+    else
+        domid = xfind_domain(dom);
+
+    if (libxl_tmem_freeze(ctx, domid) < 0)
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+int main_tmem_thaw(int argc, char **argv)
+{
+    uint32_t domid;
+    const char *dom = NULL;
+    int all = 0;
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "a", NULL, "tmem-thaw", 0) {
+    case 'a':
+        all = 1;
+        break;
+    }
+
+    dom = argv[optind];
+    if (!dom && all == 0) {
+        fprintf(stderr, "You must specify -a or a domain id.\n\n");
+        help("tmem-thaw");
+        return EXIT_FAILURE;
+    }
+
+    if (all)
+        domid = INVALID_DOMID;
+    else
+        domid = xfind_domain(dom);
+
+    if (libxl_tmem_thaw(ctx, domid) < 0)
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+int main_tmem_set(int argc, char **argv)
+{
+    uint32_t domid;
+    const char *dom = NULL;
+    uint32_t weight = 0, cap = 0, compress = 0;
+    int opt_w = 0, opt_c = 0, opt_p = 0;
+    int all = 0;
+    int opt;
+    int rc = 0;
+
+    SWITCH_FOREACH_OPT(opt, "aw:c:p:", NULL, "tmem-set", 0) {
+    case 'a':
+        all = 1;
+        break;
+    case 'w':
+        weight = strtol(optarg, NULL, 10);
+        opt_w = 1;
+        break;
+    case 'c':
+        cap = strtol(optarg, NULL, 10);
+        opt_c = 1;
+        break;
+    case 'p':
+        compress = strtol(optarg, NULL, 10);
+        opt_p = 1;
+        break;
+    }
+
+    dom = argv[optind];
+    if (!dom && all == 0) {
+        fprintf(stderr, "You must specify -a or a domain id.\n\n");
+        help("tmem-set");
+        return EXIT_FAILURE;
+    }
+
+    if (all)
+        domid = INVALID_DOMID;
+    else
+        domid = xfind_domain(dom);
+
+    if (!opt_w && !opt_c && !opt_p) {
+        fprintf(stderr, "No set value specified.\n\n");
+        help("tmem-set");
+        return EXIT_FAILURE;
+    }
+
+    if (opt_w)
+        rc = libxl_tmem_set(ctx, domid, "weight", weight);
+    if (opt_c)
+        rc = libxl_tmem_set(ctx, domid, "cap", cap);
+    if (opt_p)
+        rc = libxl_tmem_set(ctx, domid, "compress", compress);
+
+    if (rc < 0)
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+int main_tmem_shared_auth(int argc, char **argv)
+{
+    uint32_t domid;
+    const char *autharg = NULL;
+    char *endptr = NULL;
+    const char *dom = NULL;
+    char *uuid = NULL;
+    int auth = -1;
+    int all = 0;
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "au:A:", NULL, "tmem-shared-auth", 0) {
+    case 'a':
+        all = 1;
+        break;
+    case 'u':
+        uuid = optarg;
+        break;
+    case 'A':
+        autharg = optarg;
+        break;
+    }
+
+    dom = argv[optind];
+    if (!dom && all == 0) {
+        fprintf(stderr, "You must specify -a or a domain id.\n\n");
+        help("tmem-shared-auth");
+        return EXIT_FAILURE;
+    }
+
+    if (all)
+        domid = INVALID_DOMID;
+    else
+        domid = xfind_domain(dom);
+
+    if (uuid == NULL || autharg == NULL) {
+        fprintf(stderr, "No uuid or auth specified.\n\n");
+        help("tmem-shared-auth");
+        return EXIT_FAILURE;
+    }
+
+    auth = strtol(autharg, &endptr, 10);
+    if (*endptr != '\0') {
+        fprintf(stderr, "Invalid auth, valid auth are <0|1>.\n\n");
+        return EXIT_FAILURE;
+    }
+
+    if (libxl_tmem_shared_auth(ctx, domid, uuid, auth) < 0)
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+int main_tmem_freeable(int argc, char **argv)
+{
+    int opt;
+    int mb;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "tmem-freeable", 0) {
+        /* No options */
+    }
+
+    mb = libxl_tmem_freeable(ctx);
+    if (mb == -1)
+        return EXIT_FAILURE;
+
+    printf("%d\n", mb);
+    return EXIT_SUCCESS;
+}
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 10/29] xl: split out xl_parse.[ch]
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (8 preceding siblings ...)
  2017-02-24 16:12 ` [PATCH 09/29] xl: split out tmem related code to xl_tmem.c Wei Liu
@ 2017-02-24 16:12 ` Wei Liu
  2017-02-27 15:57   ` Ian Jackson
  2017-02-24 16:12 ` [PATCH 11/29] xl: split out cpupool related code Wei Liu
                   ` (18 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:12 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Move all parsing code into xl_parse.c. Export the ones needed in
xl_parse.h.

Some notable changes other than code movement:
1. rename cpurange_parse to parse_cpurange;
2. provide a function to return shutdown action name.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |    2 +-
 tools/xl/xl_cmdimpl.c | 2353 ++++---------------------------------------------
 tools/xl/xl_parse.c   | 2052 ++++++++++++++++++++++++++++++++++++++++++
 tools/xl/xl_parse.h   |   65 ++
 4 files changed, 2288 insertions(+), 2184 deletions(-)
 create mode 100644 tools/xl/xl_parse.c
 create mode 100644 tools/xl/xl_parse.h

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index f5df366e0a..d7f7f01549 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -16,7 +16,7 @@ CFLAGS_XL += $(CFLAGS_libxenlight)
 CFLAGS_XL += -Wshadow
 
 XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
-XL_OBJS += xl_tmem.o
+XL_OBJS += xl_tmem.o xl_parse.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index 3c037eb2ec..812f570d0d 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -39,6 +39,7 @@
 #include <libxlutil.h>
 #include "xl.h"
 #include "xl_utils.h"
+#include "xl_parse.h"
 
 int logfile = 2;
 
@@ -86,21 +87,6 @@ struct save_file_header {
     uint32_t optional_data_len; /* skip, or skip tail, if not understood */
 };
 
-
-static const char *action_on_shutdown_names[] = {
-    [LIBXL_ACTION_ON_SHUTDOWN_DESTROY] = "destroy",
-
-    [LIBXL_ACTION_ON_SHUTDOWN_RESTART] = "restart",
-    [LIBXL_ACTION_ON_SHUTDOWN_RESTART_RENAME] = "rename-restart",
-
-    [LIBXL_ACTION_ON_SHUTDOWN_PRESERVE] = "preserve",
-
-    [LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY] = "coredump-destroy",
-    [LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_RESTART] = "coredump-restart",
-
-    [LIBXL_ACTION_ON_SHUTDOWN_SOFT_RESET] = "soft-reset",
-};
-
 /* Optional data, in order:
  *   4 bytes uint32_t  config file size
  *   n bytes           config file in Unix text file format
@@ -191,2181 +177,216 @@ static int acquire_lock(void)
         return ERROR_FAIL;
     }
     if (fcntl(fd_lock, F_SETFD, FD_CLOEXEC) < 0) {
-        close(fd_lock);
-        fprintf(stderr, "cannot set cloexec to lockfile %s errno=%d\n", lockfile, errno);
-        return ERROR_FAIL;
-    }
-get_lock:
-    rc = fcntl(fd_lock, F_SETLKW, &fl);
-    if (rc < 0 && errno == EINTR)
-        goto get_lock;
-    if (rc < 0) {
-        fprintf(stderr, "cannot acquire lock %s errno=%d\n", lockfile, errno);
-        rc = ERROR_FAIL;
-    } else
-        rc = 0;
-    return rc;
-}
-
-static int release_lock(void)
-{
-    int rc;
-    struct flock fl;
-
-    /* lock not acquired */
-    if (fd_lock < 0)
-        return ERROR_INVAL;
-
-release_lock:
-    fl.l_type = F_UNLCK;
-    fl.l_whence = SEEK_SET;
-    fl.l_start = 0;
-    fl.l_len = 0;
-
-    rc = fcntl(fd_lock, F_SETLKW, &fl);
-    if (rc < 0 && errno == EINTR)
-        goto release_lock;
-    if (rc < 0) {
-        fprintf(stderr, "cannot release lock %s, errno=%d\n", lockfile, errno);
-        rc = ERROR_FAIL;
-    } else
-        rc = 0;
-    close(fd_lock);
-    fd_lock = -1;
-
-    return rc;
-}
-
-
-#define ARRAY_EXTEND_INIT__CORE(array,count,initfn,more)                \
-    ({                                                                  \
-        typeof((count)) array_extend_old_count = (count);               \
-        (count)++;                                                      \
-        (array) = xrealloc((array), sizeof(*array) * (count));          \
-        (initfn)(&(array)[array_extend_old_count]);                     \
-        more;                                                           \
-        &(array)[array_extend_old_count];                               \
-    })
-
-#define ARRAY_EXTEND_INIT(array,count,initfn)                           \
-    ARRAY_EXTEND_INIT__CORE((array),(count),(initfn), ({                \
-        (array)[array_extend_old_count].devid = array_extend_old_count; \
-        }))
-
-#define ARRAY_EXTEND_INIT_NODEVID(array,count,initfn) \
-    ARRAY_EXTEND_INIT__CORE((array),(count),(initfn), /* nothing */ )
-
-static yajl_gen_status printf_info_one_json(yajl_gen hand, int domid,
-                                            libxl_domain_config *d_config)
-{
-    yajl_gen_status s;
-
-    s = yajl_gen_map_open(hand);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_string(hand, (const unsigned char *)"domid",
-                        sizeof("domid")-1);
-    if (s != yajl_gen_status_ok)
-        goto out;
-    if (domid != -1)
-        s = yajl_gen_integer(hand, domid);
-    else
-        s = yajl_gen_null(hand);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_string(hand, (const unsigned char *)"config",
-                        sizeof("config")-1);
-    if (s != yajl_gen_status_ok)
-        goto out;
-    s = libxl_domain_config_gen_json(hand, d_config);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_map_close(hand);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-out:
-    return s;
-}
-
-static void printf_info(enum output_format output_format,
-                        int domid,
-                        libxl_domain_config *d_config, FILE *fh)
-{
-    if (output_format == OUTPUT_FORMAT_SXP)
-        return printf_info_sexp(domid, d_config, fh);
-
-    const char *buf;
-    libxl_yajl_length len = 0;
-    yajl_gen_status s;
-    yajl_gen hand;
-
-    hand = libxl_yajl_gen_alloc(NULL);
-    if (!hand) {
-        fprintf(stderr, "unable to allocate JSON generator\n");
-        return;
-    }
-
-    s = printf_info_one_json(hand, domid, d_config);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_get_buf(hand, (const unsigned char **)&buf, &len);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    fputs(buf, fh);
-
-out:
-    yajl_gen_free(hand);
-
-    if (s != yajl_gen_status_ok)
-        fprintf(stderr,
-                "unable to format domain config as JSON (YAJL:%d)\n", s);
-
-    xflush_stream(fh);
-}
-
-static int do_daemonize(char *name, const char *pidfile)
-{
-    char *fullname;
-    pid_t child1;
-    int nullfd, ret = 0;
-
-    child1 = xl_fork(child_waitdaemon, "domain monitoring daemonizing child");
-    if (child1) {
-        ret = child_report(child_waitdaemon);
-        if (ret) goto out;
-        ret = 1;
-        goto out;
-    }
-
-    postfork();
-
-    ret = libxl_create_logfile(ctx, name, &fullname);
-    if (ret) {
-        LOG("failed to open logfile %s: %s",fullname,strerror(errno));
-        exit(-1);
-    }
-
-    CHK_SYSCALL(logfile = open(fullname, O_WRONLY|O_CREAT|O_APPEND, 0644));
-    free(fullname);
-    assert(logfile >= 3);
-
-    CHK_SYSCALL(nullfd = open("/dev/null", O_RDONLY));
-    assert(nullfd >= 3);
-
-    dup2(nullfd, 0);
-    dup2(logfile, 1);
-    dup2(logfile, 2);
-
-    close(nullfd);
-
-    CHK_SYSCALL(daemon(0, 1));
-
-    if (pidfile) {
-        int fd = open(pidfile, O_RDWR | O_CREAT, S_IRUSR|S_IWUSR);
-        char *pid = NULL;
-
-        if (fd == -1) {
-            perror("Unable to open pidfile");
-            exit(1);
-        }
-
-        if (asprintf(&pid, "%ld\n", (long)getpid()) == -1) {
-            perror("Formatting pid");
-            exit(1);
-        }
-
-        if (write(fd, pid, strlen(pid)) < 0) {
-            perror("Writing pid");
-            exit(1);
-        }
-
-        if (close(fd) < 0) {
-            perror("Closing pidfile");
-            exit(1);
-        }
-
-        free(pid);
-    }
-
-out:
-    return ret;
-}
-
-static int parse_action_on_shutdown(const char *buf, libxl_action_on_shutdown *a)
-{
-    int i;
-    const char *n;
-
-    for (i = 0; i < sizeof(action_on_shutdown_names) / sizeof(action_on_shutdown_names[0]); i++) {
-        n = action_on_shutdown_names[i];
-
-        if (!n) continue;
-
-        if (strcmp(buf, n) == 0) {
-            *a = i;
-            return 1;
-        }
-    }
-    return 0;
-}
-
-#define DSTATE_INITIAL   0
-#define DSTATE_TAP       1
-#define DSTATE_PHYSPATH  2
-#define DSTATE_VIRTPATH  3
-#define DSTATE_VIRTTYPE  4
-#define DSTATE_RW        5
-#define DSTATE_TERMINAL  6
-
-static void parse_disk_config_multistring(XLU_Config **config,
-                                          int nspecs, const char *const *specs,
-                                          libxl_device_disk *disk)
-{
-    int e;
-
-    libxl_device_disk_init(disk);
-
-    if (!*config) {
-        *config = xlu_cfg_init(stderr, "command line");
-        if (!*config) { perror("xlu_cfg_init"); exit(-1); }
-    }
-
-    e = xlu_disk_parse(*config, nspecs, specs, disk);
-    if (e == EINVAL) exit(EXIT_FAILURE);
-    if (e) {
-        fprintf(stderr,"xlu_disk_parse failed: %s\n",strerror(errno));
-        exit(EXIT_FAILURE);
-    }
-}
-
-static void parse_disk_config(XLU_Config **config, const char *spec,
-                              libxl_device_disk *disk)
-{
-    parse_disk_config_multistring(config, 1, &spec, disk);
-}
-
-static void parse_vif_rate(XLU_Config **config, const char *rate,
-                           libxl_device_nic *nic)
-{
-    int e;
-
-    e = xlu_vif_parse_rate(*config, rate, nic);
-    if (e == EINVAL || e == EOVERFLOW) exit(EXIT_FAILURE);
-    if (e) {
-        fprintf(stderr,"xlu_vif_parse_rate failed: %s\n",strerror(errno));
-        exit(EXIT_FAILURE);
-    }
-}
-
-static void set_default_nic_values(libxl_device_nic *nic)
-{
-
-    if (default_vifscript) {
-        free(nic->script);
-        nic->script = strdup(default_vifscript);
-    }
-
-    if (default_bridge) {
-        free(nic->bridge);
-        nic->bridge = strdup(default_bridge);
-    }
-
-    if (default_gatewaydev) {
-        free(nic->gatewaydev);
-        nic->gatewaydev = strdup(default_gatewaydev);
-    }
-
-    if (default_vifbackend) {
-        free(nic->backend_domname);
-        nic->backend_domname = strdup(default_vifbackend);
-    }
-}
-
-static void split_string_into_string_list(const char *str,
-                                          const char *delim,
-                                          libxl_string_list *psl)
-{
-    char *s, *saveptr;
-    const char *p;
-    libxl_string_list sl;
-
-    int i = 0, nr = 0;
-
-    s = strdup(str);
-    if (s == NULL) {
-        fprintf(stderr, "unable to allocate memory to split string\n");
-        exit(-1);
-    }
-
-    /* Count number of entries */
-    p = strtok_r(s, delim, &saveptr);
-    do {
-        nr++;
-    } while ((p = strtok_r(NULL, delim, &saveptr)));
-
-    free(s);
-
-    s = strdup(str);
-
-    sl = malloc((nr+1) * sizeof (char *));
-    if (sl == NULL) {
-        fprintf(stderr, "unable to allocate memory to split string\n");
-        exit(-1);
-    }
-
-    p = strtok_r(s, delim, &saveptr);
-    do {
-        assert(i < nr);
-        sl[i] = strdup(p);
-        i++;
-    } while ((p = strtok_r(NULL, delim, &saveptr)));
-    sl[i] = NULL;
-
-    *psl = sl;
-
-    free(s);
-}
-
-/* NB: this follows the interface used by <ctype.h>. See 'man 3 ctype'
-   and look for CTYPE in libxl_internal.h */
-typedef int (*char_predicate_t)(const int c);
-
-static void trim(char_predicate_t predicate, const char *input, char **output)
-{
-    const char *first, *after;
-
-    for (first = input;
-         *first && predicate((unsigned char)first[0]);
-         first++)
-        ;
-
-    for (after = first + strlen(first);
-         after > first && predicate((unsigned char)after[-1]);
-         after--)
-        ;
-
-    size_t len_nonnull = after - first;
-    char *result = xmalloc(len_nonnull + 1);
-
-    memcpy(result, first, len_nonnull);
-    result[len_nonnull] = 0;
-
-    *output = result;
-}
-
-static int split_string_into_pair(const char *str,
-                                  const char *delim,
-                                  char **a,
-                                  char **b)
-{
-    char *s, *p, *saveptr, *aa = NULL, *bb = NULL;
-    int rc = 0;
-
-    s = xstrdup(str);
-
-    p = strtok_r(s, delim, &saveptr);
-    if (p == NULL) {
-        rc = ERROR_INVAL;
-        goto out;
-    }
-    aa = xstrdup(p);
-    p = strtok_r(NULL, delim, &saveptr);
-    if (p == NULL) {
-        rc = ERROR_INVAL;
-        goto out;
-    }
-    bb = xstrdup(p);
-
-    *a = aa;
-    aa = NULL;
-    *b = bb;
-    bb = NULL;
-out:
-    free(s);
-    free(aa);
-    free(bb);
-    return rc;
-}
-
-static int parse_range(const char *str, unsigned long *a, unsigned long *b)
-{
-    const char *nstr;
-    char *endptr;
-
-    *a = *b = strtoul(str, &endptr, 10);
-    if (endptr == str || *a == ULONG_MAX)
-        return 1;
-
-    if (*endptr == '-') {
-        nstr = endptr + 1;
-
-        *b = strtoul(nstr, &endptr, 10);
-        if (endptr == nstr || *b == ULONG_MAX || *b < *a)
-            return 1;
-    }
-
-    /* Valid value or range so far, but we also don't want junk after that */
-    if (*endptr != '\0')
-        return 1;
-
-    return 0;
-}
-
-/*
- * Add or removes a specific set of cpus (specified in str, either as
- * single cpus or as entire NUMA nodes) to/from cpumap.
- */
-static int update_cpumap_range(const char *str, libxl_bitmap *cpumap)
-{
-    unsigned long ida, idb;
-    libxl_bitmap node_cpumap;
-    bool is_not = false, is_nodes = false;
-    int rc = 0;
-
-    libxl_bitmap_init(&node_cpumap);
-
-    rc = libxl_node_bitmap_alloc(ctx, &node_cpumap, 0);
-    if (rc) {
-        fprintf(stderr, "libxl_node_bitmap_alloc failed.\n");
-        goto out;
-    }
-
-    /* Are we adding or removing cpus/nodes? */
-    if (STR_SKIP_PREFIX(str, "^")) {
-        is_not = true;
-    }
-
-    /* Are we dealing with cpus or full nodes? */
-    if (STR_SKIP_PREFIX(str, "node:") || STR_SKIP_PREFIX(str, "nodes:")) {
-        is_nodes = true;
-    }
-
-    if (strcmp(str, "all") == 0) {
-        /* We do not accept "^all" or "^nodes:all" */
-        if (is_not) {
-            fprintf(stderr, "Can't combine \"^\" and \"all\".\n");
-            rc = ERROR_INVAL;
-        } else
-            libxl_bitmap_set_any(cpumap);
-        goto out;
-    }
-
-    rc = parse_range(str, &ida, &idb);
-    if (rc) {
-        fprintf(stderr, "Invalid pcpu range: %s.\n", str);
-        goto out;
-    }
-
-    /* Add or remove the specified cpus in the range */
-    while (ida <= idb) {
-        if (is_nodes) {
-            /* Add/Remove all the cpus of a NUMA node */
-            int i;
-
-            rc = libxl_node_to_cpumap(ctx, ida, &node_cpumap);
-            if (rc) {
-                fprintf(stderr, "libxl_node_to_cpumap failed.\n");
-                goto out;
-            }
-
-            /* Add/Remove all the cpus in the node cpumap */
-            libxl_for_each_set_bit(i, node_cpumap) {
-                is_not ? libxl_bitmap_reset(cpumap, i) :
-                         libxl_bitmap_set(cpumap, i);
-            }
-        } else {
-            /* Add/Remove this cpu */
-            is_not ? libxl_bitmap_reset(cpumap, ida) :
-                     libxl_bitmap_set(cpumap, ida);
-        }
-        ida++;
-    }
-
- out:
-    libxl_bitmap_dispose(&node_cpumap);
-    return rc;
-}
-
-/*
- * Takes a string representing a set of cpus (specified either as
- * single cpus or as eintire NUMA nodes) and turns it into the
- * corresponding libxl_bitmap (in cpumap).
- */
-static int cpurange_parse(const char *cpu, libxl_bitmap *cpumap)
-{
-    char *ptr, *saveptr = NULL, *buf = xstrdup(cpu);
-    int rc = 0;
-
-    for (ptr = strtok_r(buf, ",", &saveptr); ptr;
-         ptr = strtok_r(NULL, ",", &saveptr)) {
-        rc = update_cpumap_range(ptr, cpumap);
-        if (rc)
-            break;
-    }
-    free(buf);
-
-    return rc;
-}
-
-static void parse_top_level_vnc_options(XLU_Config *config,
-                                        libxl_vnc_info *vnc)
-{
-    long l;
-
-    xlu_cfg_get_defbool(config, "vnc", &vnc->enable, 0);
-    xlu_cfg_replace_string (config, "vnclisten", &vnc->listen, 0);
-    xlu_cfg_replace_string (config, "vncpasswd", &vnc->passwd, 0);
-    if (!xlu_cfg_get_long (config, "vncdisplay", &l, 0))
-        vnc->display = l;
-    xlu_cfg_get_defbool(config, "vncunused", &vnc->findunused, 0);
-}
-
-static void parse_top_level_sdl_options(XLU_Config *config,
-                                        libxl_sdl_info *sdl)
-{
-    xlu_cfg_get_defbool(config, "sdl", &sdl->enable, 0);
-    xlu_cfg_get_defbool(config, "opengl", &sdl->opengl, 0);
-    xlu_cfg_replace_string (config, "display", &sdl->display, 0);
-    xlu_cfg_replace_string (config, "xauthority", &sdl->xauthority, 0);
-}
-
-static char *parse_cmdline(XLU_Config *config)
-{
-    char *cmdline = NULL;
-    const char *root = NULL, *extra = NULL, *buf = NULL;
-
-    xlu_cfg_get_string (config, "cmdline", &buf, 0);
-    xlu_cfg_get_string (config, "root", &root, 0);
-    xlu_cfg_get_string (config, "extra", &extra, 0);
-
-    if (buf) {
-        cmdline = strdup(buf);
-        if (root || extra)
-            fprintf(stderr, "Warning: ignoring root= and extra= "
-                    "in favour of cmdline=\n");
-    } else {
-        if (root && extra) {
-            xasprintf(&cmdline, "root=%s %s", root, extra);
-        } else if (root) {
-            xasprintf(&cmdline, "root=%s", root);
-        } else if (extra) {
-            cmdline = strdup(extra);
-        }
-    }
-
-    if ((buf || root || extra) && !cmdline) {
-        fprintf(stderr, "Failed to allocate memory for cmdline\n");
-        exit(EXIT_FAILURE);
-    }
-
-    return cmdline;
-}
-
-static void parse_vcpu_affinity(libxl_domain_build_info *b_info,
-                                XLU_ConfigList *cpus, const char *buf,
-                                int num_cpus, bool is_hard)
-{
-    libxl_bitmap *vcpu_affinity_array;
-
-    /*
-     * If we are here, and buf is !NULL, we're dealing with a string. What
-     * we do in this case is parse it, and copy the result in _all_ (up to
-     * b_info->max_vcpus) the elements of the vcpu affinity array.
-     *
-     * If buf is NULL, we have a list, and what we do is putting in the
-     * i-eth element of the vcpu affinity array the result of the parsing
-     * of the i-eth entry of the list. If there are more vcpus than
-     * entries, it is fine to just not touch the last array elements.
-     */
-
-    /* Silently ignore values corresponding to non existing vcpus */
-    if (buf || num_cpus > b_info->max_vcpus)
-        num_cpus = b_info->max_vcpus;
-
-    if (is_hard) {
-        b_info->num_vcpu_hard_affinity = num_cpus;
-        b_info->vcpu_hard_affinity = xmalloc(num_cpus * sizeof(libxl_bitmap));
-        vcpu_affinity_array = b_info->vcpu_hard_affinity;
-    } else {
-        b_info->num_vcpu_soft_affinity = num_cpus;
-        b_info->vcpu_soft_affinity = xmalloc(num_cpus * sizeof(libxl_bitmap));
-        vcpu_affinity_array = b_info->vcpu_soft_affinity;
-    }
-
-    if (!buf) {
-        int j = 0;
-
-        while ((buf = xlu_cfg_get_listitem(cpus, j)) != NULL && j < num_cpus) {
-            libxl_bitmap_init(&vcpu_affinity_array[j]);
-            if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[j], 0)) {
-                fprintf(stderr, "Unable to allocate cpumap for vcpu %d\n", j);
-                exit(EXIT_FAILURE);
-            }
-
-            if (cpurange_parse(buf, &vcpu_affinity_array[j]))
-                exit(EXIT_FAILURE);
-
-            j++;
-        }
-
-        /* We have a list of cpumaps, disable automatic placement */
-        libxl_defbool_set(&b_info->numa_placement, false);
-    } else {
-        int i;
-
-        libxl_bitmap_init(&vcpu_affinity_array[0]);
-        if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[0], 0)) {
-            fprintf(stderr, "Unable to allocate cpumap for vcpu 0\n");
-            exit(EXIT_FAILURE);
-        }
-
-        if (cpurange_parse(buf, &vcpu_affinity_array[0]))
-            exit(EXIT_FAILURE);
-
-        for (i = 1; i < b_info->max_vcpus; i++) {
-            libxl_bitmap_init(&vcpu_affinity_array[i]);
-            if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[i], 0)) {
-                fprintf(stderr, "Unable to allocate cpumap for vcpu %d\n", i);
-                exit(EXIT_FAILURE);
-            }
-            libxl_bitmap_copy(ctx, &vcpu_affinity_array[i],
-                              &vcpu_affinity_array[0]);
-        }
-
-        libxl_defbool_set(&b_info->numa_placement, false);
-    }
-}
-
-static unsigned long parse_ulong(const char *str)
-{
-    char *endptr;
-    unsigned long val;
-
-    val = strtoul(str, &endptr, 10);
-    if (endptr == str || val == ULONG_MAX) {
-        fprintf(stderr, "xl: failed to convert \"%s\" to number\n", str);
-        exit(EXIT_FAILURE);
-    }
-    return val;
-}
-
-static void replace_string(char **str, const char *val)
-{
-    free(*str);
-    *str = xstrdup(val);
-}
-
-static int match_option_size(const char *prefix, size_t len,
-        char *arg, char **argopt)
-{
-    int rc = strncmp(prefix, arg, len);
-    if (!rc) *argopt = arg+len;
-    return !rc;
-}
-#define MATCH_OPTION(prefix, arg, oparg) \
-    match_option_size((prefix "="), sizeof((prefix)), (arg), &(oparg))
-
-/* Parses network data and adds info into nic
- * Returns 1 if the input token does not match one of the keys
- * or parsed values are not correct. Successful parse returns 0 */
-static int parse_nic_config(libxl_device_nic *nic, XLU_Config **config, char *token)
-{
-    char *endptr, *oparg;
-    int i;
-    unsigned int val;
-
-    if (MATCH_OPTION("type", token, oparg)) {
-        if (!strcmp("vif", oparg)) {
-            nic->nictype = LIBXL_NIC_TYPE_VIF;
-        } else if (!strcmp("ioemu", oparg)) {
-            nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU;
-        } else {
-            fprintf(stderr, "Invalid parameter `type'.\n");
-            return 1;
-        }
-    } else if (MATCH_OPTION("mac", token, oparg)) {
-        for (i = 0; i < 6; i++) {
-            val = strtoul(oparg, &endptr, 16);
-            if ((oparg == endptr) || (val > 255)) {
-                fprintf(stderr, "Invalid parameter `mac'.\n");
-                return 1;
-            }
-            nic->mac[i] = val;
-            oparg = endptr + 1;
-        }
-    } else if (MATCH_OPTION("bridge", token, oparg)) {
-        replace_string(&nic->bridge, oparg);
-    } else if (MATCH_OPTION("netdev", token, oparg)) {
-        fprintf(stderr, "the netdev parameter is deprecated, "
-                        "please use gatewaydev instead\n");
-        replace_string(&nic->gatewaydev, oparg);
-    } else if (MATCH_OPTION("gatewaydev", token, oparg)) {
-        replace_string(&nic->gatewaydev, oparg);
-    } else if (MATCH_OPTION("ip", token, oparg)) {
-        replace_string(&nic->ip, oparg);
-    } else if (MATCH_OPTION("script", token, oparg)) {
-        replace_string(&nic->script, oparg);
-    } else if (MATCH_OPTION("backend", token, oparg)) {
-        replace_string(&nic->backend_domname, oparg);
-    } else if (MATCH_OPTION("vifname", token, oparg)) {
-        replace_string(&nic->ifname, oparg);
-    } else if (MATCH_OPTION("model", token, oparg)) {
-        replace_string(&nic->model, oparg);
-    } else if (MATCH_OPTION("rate", token, oparg)) {
-        parse_vif_rate(config, oparg, nic);
-    } else if (MATCH_OPTION("forwarddev", token, oparg)) {
-        replace_string(&nic->coloft_forwarddev, oparg);
-    } else if (MATCH_OPTION("accel", token, oparg)) {
-        fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
-    } else if (MATCH_OPTION("devid", token, oparg)) {
-        nic->devid = parse_ulong(oparg);
-    } else {
-        fprintf(stderr, "unrecognized argument `%s'\n", token);
-        return 1;
-    }
-    return 0;
-}
-
-static void parse_vnuma_config(const XLU_Config *config,
-                               libxl_domain_build_info *b_info)
-{
-    libxl_physinfo physinfo;
-    uint32_t nr_nodes;
-    XLU_ConfigList *vnuma;
-    int i, j, len, num_vnuma;
-    unsigned long max_vcpus = 0, max_memkb = 0;
-    /* Temporary storage for parsed vcpus information to avoid
-     * parsing config twice. This array has num_vnuma elements.
-     */
-    libxl_bitmap *vcpu_parsed;
-
-    libxl_physinfo_init(&physinfo);
-    if (libxl_get_physinfo(ctx, &physinfo) != 0) {
-        libxl_physinfo_dispose(&physinfo);
-        fprintf(stderr, "libxl_get_physinfo failed\n");
-        exit(EXIT_FAILURE);
-    }
-
-    nr_nodes = physinfo.nr_nodes;
-    libxl_physinfo_dispose(&physinfo);
-
-    if (xlu_cfg_get_list(config, "vnuma", &vnuma, &num_vnuma, 1))
-        return;
-
-    if (!num_vnuma)
-        return;
-
-    b_info->num_vnuma_nodes = num_vnuma;
-    b_info->vnuma_nodes = xcalloc(num_vnuma, sizeof(libxl_vnode_info));
-    vcpu_parsed = xcalloc(num_vnuma, sizeof(libxl_bitmap));
-    for (i = 0; i < num_vnuma; i++) {
-        libxl_bitmap_init(&vcpu_parsed[i]);
-        if (libxl_cpu_bitmap_alloc(ctx, &vcpu_parsed[i], b_info->max_vcpus)) {
-            fprintf(stderr, "libxl_node_bitmap_alloc failed.\n");
-            exit(EXIT_FAILURE);
-        }
-    }
-
-    for (i = 0; i < b_info->num_vnuma_nodes; i++) {
-        libxl_vnode_info *p = &b_info->vnuma_nodes[i];
-
-        libxl_vnode_info_init(p);
-        p->distances = xcalloc(b_info->num_vnuma_nodes,
-                               sizeof(*p->distances));
-        p->num_distances = b_info->num_vnuma_nodes;
-    }
-
-    for (i = 0; i < num_vnuma; i++) {
-        XLU_ConfigValue *vnode_spec, *conf_option;
-        XLU_ConfigList *vnode_config_list;
-        int conf_count;
-        libxl_vnode_info *p = &b_info->vnuma_nodes[i];
-
-        vnode_spec = xlu_cfg_get_listitem2(vnuma, i);
-        assert(vnode_spec);
-
-        xlu_cfg_value_get_list(config, vnode_spec, &vnode_config_list, 0);
-        if (!vnode_config_list) {
-            fprintf(stderr, "xl: cannot get vnode config option list\n");
-            exit(EXIT_FAILURE);
-        }
-
-        for (conf_count = 0;
-             (conf_option =
-              xlu_cfg_get_listitem2(vnode_config_list, conf_count));
-             conf_count++) {
-
-            if (xlu_cfg_value_type(conf_option) == XLU_STRING) {
-                char *buf, *option_untrimmed, *value_untrimmed;
-                char *option, *value;
-                unsigned long val;
-
-                xlu_cfg_value_get_string(config, conf_option, &buf, 0);
-
-                if (!buf) continue;
-
-                if (split_string_into_pair(buf, "=",
-                                           &option_untrimmed,
-                                           &value_untrimmed)) {
-                    fprintf(stderr, "xl: failed to split \"%s\" into pair\n",
-                            buf);
-                    exit(EXIT_FAILURE);
-                }
-                trim(isspace, option_untrimmed, &option);
-                trim(isspace, value_untrimmed, &value);
-
-                if (!strcmp("pnode", option)) {
-                    val = parse_ulong(value);
-                    if (val >= nr_nodes) {
-                        fprintf(stderr,
-                                "xl: invalid pnode number: %lu\n", val);
-                        exit(EXIT_FAILURE);
-                    }
-                    p->pnode = val;
-                    libxl_defbool_set(&b_info->numa_placement, false);
-                } else if (!strcmp("size", option)) {
-                    val = parse_ulong(value);
-                    p->memkb = val << 10;
-                    max_memkb += p->memkb;
-                } else if (!strcmp("vcpus", option)) {
-                    libxl_string_list cpu_spec_list;
-                    unsigned long s, e;
-
-                    split_string_into_string_list(value, ",", &cpu_spec_list);
-                    len = libxl_string_list_length(&cpu_spec_list);
-
-                    for (j = 0; j < len; j++) {
-                        parse_range(cpu_spec_list[j], &s, &e);
-                        for (; s <= e; s++) {
-                            /*
-                             * Note that if we try to set a bit beyond
-                             * the size of bitmap, libxl_bitmap_set
-                             * has no effect. The resulted bitmap
-                             * doesn't reflect what user wants. The
-                             * fallout is dealt with later after
-                             * parsing.
-                             */
-                            libxl_bitmap_set(&vcpu_parsed[i], s);
-                            max_vcpus++;
-                        }
-                    }
-
-                    libxl_string_list_dispose(&cpu_spec_list);
-                } else if (!strcmp("vdistances", option)) {
-                    libxl_string_list vdist;
-
-                    split_string_into_string_list(value, ",", &vdist);
-                    len = libxl_string_list_length(&vdist);
-
-                    for (j = 0; j < len; j++) {
-                        val = parse_ulong(vdist[j]);
-                        p->distances[j] = val;
-                    }
-                    libxl_string_list_dispose(&vdist);
-                }
-                free(option);
-                free(value);
-                free(option_untrimmed);
-                free(value_untrimmed);
-            }
-        }
-    }
-
-    /* User has specified maxvcpus= */
-    if (b_info->max_vcpus != 0) {
-        if (b_info->max_vcpus != max_vcpus) {
-            fprintf(stderr, "xl: vnuma vcpus and maxvcpus= mismatch\n");
-            exit(EXIT_FAILURE);
-        }
-    } else {
-        int host_cpus = libxl_get_online_cpus(ctx);
-
-        if (host_cpus < 0) {
-            fprintf(stderr, "Failed to get online cpus\n");
-            exit(EXIT_FAILURE);
-        }
-
-        if (host_cpus < max_vcpus) {
-            fprintf(stderr, "xl: vnuma specifies more vcpus than pcpus, "\
-                    "use maxvcpus= to override this check.\n");
-            exit(EXIT_FAILURE);
-        }
-
-        b_info->max_vcpus = max_vcpus;
-    }
-
-    /* User has specified maxmem= */
-    if (b_info->max_memkb != LIBXL_MEMKB_DEFAULT &&
-        b_info->max_memkb != max_memkb) {
-        fprintf(stderr, "xl: maxmem and vnuma memory size mismatch\n");
-        exit(EXIT_FAILURE);
-    } else
-        b_info->max_memkb = max_memkb;
-
-    for (i = 0; i < b_info->num_vnuma_nodes; i++) {
-        libxl_vnode_info *p = &b_info->vnuma_nodes[i];
-
-        libxl_bitmap_copy_alloc(ctx, &p->vcpus, &vcpu_parsed[i]);
-        libxl_bitmap_dispose(&vcpu_parsed[i]);
-    }
-
-    free(vcpu_parsed);
-}
-
-/* Parses usbctrl data and adds info into usbctrl
- * Returns 1 if the input token does not match one of the keys
- * or parsed values are not correct. Successful parse returns 0 */
-static int parse_usbctrl_config(libxl_device_usbctrl *usbctrl, char *token)
-{
-    char *oparg;
-
-    if (MATCH_OPTION("type", token, oparg)) {
-        if (libxl_usbctrl_type_from_string(oparg, &usbctrl->type)) {
-            fprintf(stderr, "Invalid usb controller type '%s'\n", oparg);
-            return 1;
-        }
-    } else if (MATCH_OPTION("version", token, oparg)) {
-        usbctrl->version = atoi(oparg);
-    } else if (MATCH_OPTION("ports", token, oparg)) {
-        usbctrl->ports = atoi(oparg);
-    } else {
-        fprintf(stderr, "Unknown string `%s' in usbctrl spec\n", token);
-        return 1;
-    }
-
-    return 0;
-}
-
-/* Parses usbdev data and adds info into usbdev
- * Returns 1 if the input token does not match one of the keys
- * or parsed values are not correct. Successful parse returns 0 */
-static int parse_usbdev_config(libxl_device_usbdev *usbdev, char *token)
-{
-    char *oparg;
-
-    if (MATCH_OPTION("type", token, oparg)) {
-        if (libxl_usbdev_type_from_string(oparg, &usbdev->type)) {
-            fprintf(stderr, "Invalid usb device type: %s\n", optarg);
-            return 1;
-        }
-    } else if (MATCH_OPTION("hostbus", token, oparg)) {
-        usbdev->u.hostdev.hostbus = strtoul(oparg, NULL, 0);
-    } else if (MATCH_OPTION("hostaddr", token, oparg)) {
-        usbdev->u.hostdev.hostaddr = strtoul(oparg, NULL, 0);
-    } else if (MATCH_OPTION("controller", token, oparg)) {
-        usbdev->ctrl = atoi(oparg);
-    } else if (MATCH_OPTION("port", token, oparg)) {
-        usbdev->port = atoi(oparg);
-    } else {
-        fprintf(stderr, "Unknown string `%s' in usbdev spec\n", token);
-        return 1;
-    }
-
-    return 0;
-}
-
-static void parse_config_data(const char *config_source,
-                              const char *config_data,
-                              int config_len,
-                              libxl_domain_config *d_config)
-{
-    const char *buf;
-    long l, vcpus = 0;
-    XLU_Config *config;
-    XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms,
-                   *usbctrls, *usbdevs;
-    XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs;
-    int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian;
-    int pci_power_mgmt = 0;
-    int pci_msitranslate = 0;
-    int pci_permissive = 0;
-    int pci_seize = 0;
-    int i, e;
-    char *kernel_basename;
-
-    libxl_domain_create_info *c_info = &d_config->c_info;
-    libxl_domain_build_info *b_info = &d_config->b_info;
-
-    config= xlu_cfg_init(stderr, config_source);
-    if (!config) {
-        fprintf(stderr, "Failed to allocate for configuration\n");
-        exit(1);
-    }
-
-    e= xlu_cfg_readdata(config, config_data, config_len);
-    if (e) {
-        fprintf(stderr, "Failed to parse config: %s\n", strerror(e));
-        exit(1);
-    }
-
-    if (!xlu_cfg_get_string (config, "init_seclabel", &buf, 0))
-        xlu_cfg_replace_string(config, "init_seclabel",
-                               &c_info->ssid_label, 0);
-
-    if (!xlu_cfg_get_string (config, "seclabel", &buf, 0)) {
-        if (c_info->ssid_label)
-            xlu_cfg_replace_string(config, "seclabel",
-                                   &b_info->exec_ssid_label, 0);
-        else
-            xlu_cfg_replace_string(config, "seclabel",
-                                   &c_info->ssid_label, 0);
-    }
-
-    libxl_defbool_set(&c_info->run_hotplug_scripts, run_hotplug_scripts);
-    c_info->type = LIBXL_DOMAIN_TYPE_PV;
-    if (!xlu_cfg_get_string (config, "builder", &buf, 0) &&
-        !strncmp(buf, "hvm", strlen(buf)))
-        c_info->type = LIBXL_DOMAIN_TYPE_HVM;
-
-    xlu_cfg_get_defbool(config, "pvh", &c_info->pvh, 0);
-    xlu_cfg_get_defbool(config, "hap", &c_info->hap, 0);
-
-    if (xlu_cfg_replace_string (config, "name", &c_info->name, 0)) {
-        fprintf(stderr, "Domain name must be specified.\n");
-        exit(1);
-    }
-
-    if (!xlu_cfg_get_string (config, "uuid", &buf, 0) ) {
-        if ( libxl_uuid_from_string(&c_info->uuid, buf) ) {
-            fprintf(stderr, "Failed to parse UUID: %s\n", buf);
-            exit(1);
-        }
-    }else{
-        libxl_uuid_generate(&c_info->uuid);
-    }
-
-    xlu_cfg_get_defbool(config, "oos", &c_info->oos, 0);
-
-    if (!xlu_cfg_get_string (config, "pool", &buf, 0))
-        xlu_cfg_replace_string(config, "pool", &c_info->pool_name, 0);
-
-    libxl_domain_build_info_init_type(b_info, c_info->type);
-    if (blkdev_start)
-        b_info->blkdev_start = strdup(blkdev_start);
-
-    /* the following is the actual config parsing with overriding
-     * values in the structures */
-    if (!xlu_cfg_get_long (config, "cpu_weight", &l, 0))
-        b_info->sched_params.weight = l;
-    if (!xlu_cfg_get_long (config, "cap", &l, 0))
-        b_info->sched_params.cap = l;
-    if (!xlu_cfg_get_long (config, "period", &l, 0))
-        b_info->sched_params.period = l;
-    if (!xlu_cfg_get_long (config, "slice", &l, 0))
-        b_info->sched_params.slice = l;
-    if (!xlu_cfg_get_long (config, "latency", &l, 0))
-        b_info->sched_params.latency = l;
-    if (!xlu_cfg_get_long (config, "extratime", &l, 0))
-        b_info->sched_params.extratime = l;
-
-    if (!xlu_cfg_get_long (config, "memory", &l, 0))
-        b_info->target_memkb = l * 1024;
-
-    if (!xlu_cfg_get_long (config, "maxmem", &l, 0))
-        b_info->max_memkb = l * 1024;
-
-    if (!xlu_cfg_get_long (config, "vcpus", &l, 0)) {
-        vcpus = l;
-        if (libxl_cpu_bitmap_alloc(ctx, &b_info->avail_vcpus, l)) {
-            fprintf(stderr, "Unable to allocate cpumap\n");
-            exit(1);
-        }
-        libxl_bitmap_set_none(&b_info->avail_vcpus);
-        while (l-- > 0)
-            libxl_bitmap_set((&b_info->avail_vcpus), l);
-    }
-
-    if (!xlu_cfg_get_long (config, "maxvcpus", &l, 0))
-        b_info->max_vcpus = l;
-
-    parse_vnuma_config(config, b_info);
-
-    /* Set max_memkb to target_memkb and max_vcpus to avail_vcpus if
-     * they are not set by user specified config option or vnuma.
-     */
-    if (b_info->max_memkb == LIBXL_MEMKB_DEFAULT)
-        b_info->max_memkb = b_info->target_memkb;
-    if (b_info->max_vcpus == 0)
-        b_info->max_vcpus = vcpus;
-
-    if (b_info->max_vcpus < vcpus) {
-        fprintf(stderr, "xl: maxvcpus < vcpus\n");
-        exit(1);
-    }
-
-    buf = NULL;
-    if (!xlu_cfg_get_list (config, "cpus", &cpus, &num_cpus, 1) ||
-        !xlu_cfg_get_string (config, "cpus", &buf, 0))
-        parse_vcpu_affinity(b_info, cpus, buf, num_cpus, /* is_hard */ true);
-
-    buf = NULL;
-    if (!xlu_cfg_get_list (config, "cpus_soft", &cpus, &num_cpus, 1) ||
-        !xlu_cfg_get_string (config, "cpus_soft", &buf, 0))
-        parse_vcpu_affinity(b_info, cpus, buf, num_cpus, false);
-
-    libxl_defbool_set(&b_info->claim_mode, claim_mode);
-
-    if (xlu_cfg_get_string (config, "on_poweroff", &buf, 0))
-        buf = "destroy";
-    if (!parse_action_on_shutdown(buf, &d_config->on_poweroff)) {
-        fprintf(stderr, "Unknown on_poweroff action \"%s\" specified\n", buf);
-        exit(1);
-    }
-
-    if (xlu_cfg_get_string (config, "on_reboot", &buf, 0))
-        buf = "restart";
-    if (!parse_action_on_shutdown(buf, &d_config->on_reboot)) {
-        fprintf(stderr, "Unknown on_reboot action \"%s\" specified\n", buf);
-        exit(1);
-    }
-
-    if (xlu_cfg_get_string (config, "on_watchdog", &buf, 0))
-        buf = "destroy";
-    if (!parse_action_on_shutdown(buf, &d_config->on_watchdog)) {
-        fprintf(stderr, "Unknown on_watchdog action \"%s\" specified\n", buf);
-        exit(1);
-    }
-
-
-    if (xlu_cfg_get_string (config, "on_crash", &buf, 0))
-        buf = "destroy";
-    if (!parse_action_on_shutdown(buf, &d_config->on_crash)) {
-        fprintf(stderr, "Unknown on_crash action \"%s\" specified\n", buf);
-        exit(1);
-    }
-
-    if (xlu_cfg_get_string (config, "on_soft_reset", &buf, 0))
-        buf = "soft-reset";
-    if (!parse_action_on_shutdown(buf, &d_config->on_soft_reset)) {
-        fprintf(stderr, "Unknown on_soft_reset action \"%s\" specified\n", buf);
-        exit(1);
-    }
-
-    /* libxl_get_required_shadow_memory() must be called after final values
-     * (default or specified) for vcpus and memory are set, because the
-     * calculation depends on those values. */
-    b_info->shadow_memkb = !xlu_cfg_get_long(config, "shadow_memory", &l, 0)
-        ? l * 1024
-        : libxl_get_required_shadow_memory(b_info->max_memkb,
-                                           b_info->max_vcpus);
-
-    xlu_cfg_get_defbool(config, "nomigrate", &b_info->disable_migrate, 0);
-
-    if (!xlu_cfg_get_long(config, "tsc_mode", &l, 1)) {
-        const char *s = libxl_tsc_mode_to_string(l);
-        fprintf(stderr, "WARNING: specifying \"tsc_mode\" as an integer is deprecated. "
-                "Please use the named parameter variant. %s%s%s\n",
-                s ? "e.g. tsc_mode=\"" : "",
-                s ? s : "",
-                s ? "\"" : "");
-
-        if (l < LIBXL_TSC_MODE_DEFAULT ||
-            l > LIBXL_TSC_MODE_NATIVE_PARAVIRT) {
-            fprintf(stderr, "ERROR: invalid value %ld for \"tsc_mode\"\n", l);
-            exit (1);
-        }
-        b_info->tsc_mode = l;
-    } else if (!xlu_cfg_get_string(config, "tsc_mode", &buf, 0)) {
-        fprintf(stderr, "got a tsc mode string: \"%s\"\n", buf);
-        if (libxl_tsc_mode_from_string(buf, &b_info->tsc_mode)) {
-            fprintf(stderr, "ERROR: invalid value \"%s\" for \"tsc_mode\"\n",
-                    buf);
-            exit (1);
-        }
-    }
-
-    if (!xlu_cfg_get_long(config, "rtc_timeoffset", &l, 0))
-        b_info->rtc_timeoffset = l;
-
-    if (!xlu_cfg_get_long(config, "vncviewer", &l, 0))
-        fprintf(stderr, "WARNING: ignoring \"vncviewer\" option. "
-                "Use \"-V\" option of \"xl create\" to automatically spawn vncviewer.\n");
-
-    xlu_cfg_get_defbool(config, "localtime", &b_info->localtime, 0);
-
-    if (!xlu_cfg_get_long (config, "videoram", &l, 0))
-        b_info->video_memkb = l * 1024;
-
-    if (!xlu_cfg_get_long(config, "max_event_channels", &l, 0))
-        b_info->event_channels = l;
-
-    xlu_cfg_replace_string (config, "kernel", &b_info->kernel, 0);
-    xlu_cfg_replace_string (config, "ramdisk", &b_info->ramdisk, 0);
-    xlu_cfg_replace_string (config, "device_tree", &b_info->device_tree, 0);
-    b_info->cmdline = parse_cmdline(config);
-
-    xlu_cfg_get_defbool(config, "driver_domain", &c_info->driver_domain, 0);
-    xlu_cfg_get_defbool(config, "acpi", &b_info->acpi, 0);
-
-    switch(b_info->type) {
-    case LIBXL_DOMAIN_TYPE_HVM:
-        kernel_basename = libxl_basename(b_info->kernel);
-        if (!strcmp(kernel_basename, "hvmloader")) {
-            fprintf(stderr, "WARNING: you seem to be using \"kernel\" "
-                    "directive to override HVM guest firmware. Ignore "
-                    "that. Use \"firmware_override\" instead if you "
-                    "really want a non-default firmware\n");
-            b_info->kernel = NULL;
-        }
-        free(kernel_basename);
-
-        xlu_cfg_replace_string (config, "firmware_override",
-                                &b_info->u.hvm.firmware, 0);
-        xlu_cfg_replace_string (config, "bios_path_override",
-                                &b_info->u.hvm.system_firmware, 0);
-        if (!xlu_cfg_get_string(config, "bios", &buf, 0)) {
-            if (libxl_bios_type_from_string(buf, &b_info->u.hvm.bios)) {
-                fprintf(stderr, "ERROR: invalid value \"%s\" for \"bios\"\n",
-                    buf);
-                exit (1);
-            }
-        } else if (b_info->u.hvm.system_firmware)
-            fprintf(stderr, "WARNING: "
-                    "bios_path_override given without specific bios name\n");
-
-        xlu_cfg_get_defbool(config, "pae", &b_info->u.hvm.pae, 0);
-        xlu_cfg_get_defbool(config, "apic", &b_info->u.hvm.apic, 0);
-        xlu_cfg_get_defbool(config, "acpi_s3", &b_info->u.hvm.acpi_s3, 0);
-        xlu_cfg_get_defbool(config, "acpi_s4", &b_info->u.hvm.acpi_s4, 0);
-        xlu_cfg_get_defbool(config, "nx", &b_info->u.hvm.nx, 0);
-        xlu_cfg_get_defbool(config, "hpet", &b_info->u.hvm.hpet, 0);
-        xlu_cfg_get_defbool(config, "vpt_align", &b_info->u.hvm.vpt_align, 0);
-
-        switch (xlu_cfg_get_list(config, "viridian",
-                                 &viridian, &num_viridian, 1))
-        {
-        case 0: /* Success */
-            if (num_viridian) {
-                libxl_bitmap_alloc(ctx, &b_info->u.hvm.viridian_enable,
-                                   LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
-                libxl_bitmap_alloc(ctx, &b_info->u.hvm.viridian_disable,
-                                   LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
-            }
-            for (i = 0; i < num_viridian; i++) {
-                libxl_viridian_enlightenment v;
-
-                buf = xlu_cfg_get_listitem(viridian, i);
-                if (strcmp(buf, "all") == 0)
-                    libxl_bitmap_set_any(&b_info->u.hvm.viridian_enable);
-                else if (strcmp(buf, "defaults") == 0)
-                    libxl_defbool_set(&b_info->u.hvm.viridian, true);
-                else {
-                    libxl_bitmap *s = &b_info->u.hvm.viridian_enable;
-                    libxl_bitmap *r = &b_info->u.hvm.viridian_disable;
-
-                    if (*buf == '!') {
-                        s = &b_info->u.hvm.viridian_disable;
-                        r = &b_info->u.hvm.viridian_enable;
-                        buf++;
-                    }
-
-                    e = libxl_viridian_enlightenment_from_string(buf, &v);
-                    if (e) {
-                        fprintf(stderr,
-                                "xl: unknown viridian enlightenment '%s'\n",
-                                buf);
-                        exit(-ERROR_FAIL);
-                    }
-
-                    libxl_bitmap_set(s, v);
-                    libxl_bitmap_reset(r, v);
-                }
-            }
-            break;
-        case ESRCH: break; /* Option not present */
-        case EINVAL:
-            xlu_cfg_get_defbool(config, "viridian", &b_info->u.hvm.viridian, 1);
-            break;
-        default:
-            fprintf(stderr,"xl: Unable to parse viridian enlightenments.\n");
-            exit(-ERROR_FAIL);
-        }
-
-        if (!xlu_cfg_get_long(config, "mmio_hole", &l, 0)) {
-            uint64_t mmio_hole_size;
-
-            b_info->u.hvm.mmio_hole_memkb = l * 1024;
-            mmio_hole_size = b_info->u.hvm.mmio_hole_memkb * 1024;
-            if (mmio_hole_size < HVM_BELOW_4G_MMIO_LENGTH ||
-                mmio_hole_size > HVM_BELOW_4G_MMIO_START) {
-                fprintf(stderr,
-                        "ERROR: invalid value %ld for \"mmio_hole\"\n", l);
-                exit (1);
-            }
-        }
-        if (!xlu_cfg_get_long(config, "timer_mode", &l, 1)) {
-            const char *s = libxl_timer_mode_to_string(l);
-            fprintf(stderr, "WARNING: specifying \"timer_mode\" as an integer is deprecated. "
-                    "Please use the named parameter variant. %s%s%s\n",
-                    s ? "e.g. timer_mode=\"" : "",
-                    s ? s : "",
-                    s ? "\"" : "");
-
-            if (l < LIBXL_TIMER_MODE_DELAY_FOR_MISSED_TICKS ||
-                l > LIBXL_TIMER_MODE_ONE_MISSED_TICK_PENDING) {
-                fprintf(stderr, "ERROR: invalid value %ld for \"timer_mode\"\n", l);
-                exit (1);
-            }
-            b_info->u.hvm.timer_mode = l;
-        } else if (!xlu_cfg_get_string(config, "timer_mode", &buf, 0)) {
-            if (libxl_timer_mode_from_string(buf, &b_info->u.hvm.timer_mode)) {
-                fprintf(stderr, "ERROR: invalid value \"%s\" for \"timer_mode\"\n",
-                        buf);
-                exit (1);
-            }
-        }
-
-        xlu_cfg_get_defbool(config, "nestedhvm", &b_info->u.hvm.nested_hvm, 0);
-
-        xlu_cfg_get_defbool(config, "altp2mhvm", &b_info->u.hvm.altp2m, 0);
-
-        xlu_cfg_replace_string(config, "smbios_firmware",
-                               &b_info->u.hvm.smbios_firmware, 0);
-        xlu_cfg_replace_string(config, "acpi_firmware",
-                               &b_info->u.hvm.acpi_firmware, 0);
-
-        if (!xlu_cfg_get_string(config, "ms_vm_genid", &buf, 0)) {
-            if (!strcmp(buf, "generate")) {
-                e = libxl_ms_vm_genid_generate(ctx, &b_info->u.hvm.ms_vm_genid);
-                if (e) {
-                    fprintf(stderr, "ERROR: failed to generate a VM Generation ID\n");
-                    exit(1);
-                }
-            } else if (!strcmp(buf, "none")) {
-                ;
-            } else {
-                    fprintf(stderr, "ERROR: \"ms_vm_genid\" option must be \"generate\" or \"none\"\n");
-                    exit(1);
-            }
-        }
-
-        if (!xlu_cfg_get_long (config, "rdm_mem_boundary", &l, 0))
-            b_info->u.hvm.rdm_mem_boundary_memkb = l * 1024;
-        break;
-    case LIBXL_DOMAIN_TYPE_PV:
-    {
-        xlu_cfg_replace_string (config, "bootloader", &b_info->u.pv.bootloader, 0);
-        switch (xlu_cfg_get_list_as_string_list(config, "bootloader_args",
-                                      &b_info->u.pv.bootloader_args, 1))
-        {
-
-        case 0: break; /* Success */
-        case ESRCH: break; /* Option not present */
-        case EINVAL:
-            if (!xlu_cfg_get_string(config, "bootloader_args", &buf, 0)) {
-
-                fprintf(stderr, "WARNING: Specifying \"bootloader_args\""
-                        " as a string is deprecated. "
-                        "Please use a list of arguments.\n");
-                split_string_into_string_list(buf, " \t\n",
-                                              &b_info->u.pv.bootloader_args);
-            }
-            break;
-        default:
-            fprintf(stderr,"xl: Unable to parse bootloader_args.\n");
-            exit(-ERROR_FAIL);
-        }
-
-        if (!b_info->u.pv.bootloader && !b_info->kernel) {
-            fprintf(stderr, "Neither kernel nor bootloader specified\n");
-            exit(1);
-        }
-
-        break;
-    }
-    default:
-        abort();
-    }
-
-    if (!xlu_cfg_get_list(config, "ioports", &ioports, &num_ioports, 0)) {
-        b_info->num_ioports = num_ioports;
-        b_info->ioports = calloc(num_ioports, sizeof(*b_info->ioports));
-        if (b_info->ioports == NULL) {
-            fprintf(stderr, "unable to allocate memory for ioports\n");
-            exit(-1);
-        }
-
-        for (i = 0; i < num_ioports; i++) {
-            const char *buf2;
-            char *ep;
-            uint32_t start, end;
-            unsigned long ul;
-
-            buf = xlu_cfg_get_listitem (ioports, i);
-            if (!buf) {
-                fprintf(stderr,
-                        "xl: Unable to get element #%d in ioport list\n", i);
-                exit(1);
-            }
-            ul = strtoul(buf, &ep, 16);
-            if (ep == buf) {
-                fprintf(stderr, "xl: Invalid argument parsing ioport: %s\n",
-                        buf);
-                exit(1);
-            }
-            if (ul >= UINT32_MAX) {
-                fprintf(stderr, "xl: ioport %lx too big\n", ul);
-                exit(1);
-            }
-            start = end = ul;
-
-            if (*ep == '-') {
-                buf2 = ep + 1;
-                ul = strtoul(buf2, &ep, 16);
-                if (ep == buf2 || *ep != '\0' || start > end) {
-                    fprintf(stderr,
-                            "xl: Invalid argument parsing ioport: %s\n", buf);
-                    exit(1);
-                }
-                if (ul >= UINT32_MAX) {
-                    fprintf(stderr, "xl: ioport %lx too big\n", ul);
-                    exit(1);
-                }
-                end = ul;
-            } else if ( *ep != '\0' )
-                fprintf(stderr,
-                        "xl: Invalid argument parsing ioport: %s\n", buf);
-            b_info->ioports[i].first = start;
-            b_info->ioports[i].number = end - start + 1;
-        }
-    }
-
-    if (!xlu_cfg_get_list(config, "irqs", &irqs, &num_irqs, 0)) {
-        b_info->num_irqs = num_irqs;
-        b_info->irqs = calloc(num_irqs, sizeof(*b_info->irqs));
-        if (b_info->irqs == NULL) {
-            fprintf(stderr, "unable to allocate memory for ioports\n");
-            exit(-1);
-        }
-        for (i = 0; i < num_irqs; i++) {
-            char *ep;
-            unsigned long ul;
-            buf = xlu_cfg_get_listitem (irqs, i);
-            if (!buf) {
-                fprintf(stderr,
-                        "xl: Unable to get element %d in irq list\n", i);
-                exit(1);
-            }
-            ul = strtoul(buf, &ep, 10);
-            if (ep == buf || *ep != '\0') {
-                fprintf(stderr,
-                        "xl: Invalid argument parsing irq: %s\n", buf);
-                exit(1);
-            }
-            if (ul >= UINT32_MAX) {
-                fprintf(stderr, "xl: irq %lx too big\n", ul);
-                exit(1);
-            }
-            b_info->irqs[i] = ul;
-        }
+        close(fd_lock);
+        fprintf(stderr, "cannot set cloexec to lockfile %s errno=%d\n", lockfile, errno);
+        return ERROR_FAIL;
     }
+get_lock:
+    rc = fcntl(fd_lock, F_SETLKW, &fl);
+    if (rc < 0 && errno == EINTR)
+        goto get_lock;
+    if (rc < 0) {
+        fprintf(stderr, "cannot acquire lock %s errno=%d\n", lockfile, errno);
+        rc = ERROR_FAIL;
+    } else
+        rc = 0;
+    return rc;
+}
 
-    if (!xlu_cfg_get_list(config, "iomem", &iomem, &num_iomem, 0)) {
-        int ret;
-        b_info->num_iomem = num_iomem;
-        b_info->iomem = calloc(num_iomem, sizeof(*b_info->iomem));
-        if (b_info->iomem == NULL) {
-            fprintf(stderr, "unable to allocate memory for iomem\n");
-            exit(-1);
-        }
-        for (i = 0; i < num_iomem; i++) {
-            int used;
+static int release_lock(void)
+{
+    int rc;
+    struct flock fl;
 
-            buf = xlu_cfg_get_listitem (iomem, i);
-            if (!buf) {
-                fprintf(stderr,
-                        "xl: Unable to get element %d in iomem list\n", i);
-                exit(1);
-            }
-            libxl_iomem_range_init(&b_info->iomem[i]);
-            ret = sscanf(buf, "%" SCNx64",%" SCNx64"%n@%" SCNx64"%n",
-                         &b_info->iomem[i].start,
-                         &b_info->iomem[i].number, &used,
-                         &b_info->iomem[i].gfn, &used);
-            if (ret < 2 || buf[used] != '\0') {
-                fprintf(stderr,
-                        "xl: Invalid argument parsing iomem: %s\n", buf);
-                exit(1);
-            }
-        }
-    }
+    /* lock not acquired */
+    if (fd_lock < 0)
+        return ERROR_INVAL;
 
+release_lock:
+    fl.l_type = F_UNLCK;
+    fl.l_whence = SEEK_SET;
+    fl.l_start = 0;
+    fl.l_len = 0;
 
+    rc = fcntl(fd_lock, F_SETLKW, &fl);
+    if (rc < 0 && errno == EINTR)
+        goto release_lock;
+    if (rc < 0) {
+        fprintf(stderr, "cannot release lock %s, errno=%d\n", lockfile, errno);
+        rc = ERROR_FAIL;
+    } else
+        rc = 0;
+    close(fd_lock);
+    fd_lock = -1;
 
-    if (!xlu_cfg_get_list (config, "disk", &vbds, 0, 0)) {
-        d_config->num_disks = 0;
-        d_config->disks = NULL;
-        while ((buf = xlu_cfg_get_listitem (vbds, d_config->num_disks)) != NULL) {
-            libxl_device_disk *disk;
-            char *buf2 = strdup(buf);
-
-            disk = ARRAY_EXTEND_INIT_NODEVID(d_config->disks,
-                                             d_config->num_disks,
-                                             libxl_device_disk_init);
-            parse_disk_config(&config, buf2, disk);
-
-            free(buf2);
-        }
-    }
-
-    if (!xlu_cfg_get_list(config, "vtpm", &vtpms, 0, 0)) {
-        d_config->num_vtpms = 0;
-        d_config->vtpms = NULL;
-        while ((buf = xlu_cfg_get_listitem (vtpms, d_config->num_vtpms)) != NULL) {
-            libxl_device_vtpm *vtpm;
-            char * buf2 = strdup(buf);
-            char *p, *p2;
-            bool got_backend = false;
-
-            vtpm = ARRAY_EXTEND_INIT(d_config->vtpms,
-                                     d_config->num_vtpms,
-                                     libxl_device_vtpm_init);
-
-            p = strtok(buf2, ",");
-            if(p) {
-               do {
-                  while(*p == ' ')
-                     ++p;
-                  if ((p2 = strchr(p, '=')) == NULL)
-                     break;
-                  *p2 = '\0';
-                  if (!strcmp(p, "backend")) {
-                     vtpm->backend_domname = strdup(p2 + 1);
-                     got_backend = true;
-                  } else if(!strcmp(p, "uuid")) {
-                     if( libxl_uuid_from_string(&vtpm->uuid, p2 + 1) ) {
-                        fprintf(stderr,
-                              "Failed to parse vtpm UUID: %s\n", p2 + 1);
-                        exit(1);
-                    }
-                  } else {
-                     fprintf(stderr, "Unknown string `%s' in vtpm spec\n", p);
-                     exit(1);
-                  }
-               } while ((p = strtok(NULL, ",")) != NULL);
-            }
-            if(!got_backend) {
-               fprintf(stderr, "vtpm spec missing required backend field!\n");
-               exit(1);
-            }
-            free(buf2);
-        }
-    }
-
-    if (!xlu_cfg_get_list (config, "channel", &channels, 0, 0)) {
-        d_config->num_channels = 0;
-        d_config->channels = NULL;
-        while ((buf = xlu_cfg_get_listitem (channels,
-                d_config->num_channels)) != NULL) {
-            libxl_device_channel *chn;
-            libxl_string_list pairs;
-            char *path = NULL;
-            int len;
-
-            chn = ARRAY_EXTEND_INIT(d_config->channels, d_config->num_channels,
-                                   libxl_device_channel_init);
-
-            split_string_into_string_list(buf, ",", &pairs);
-            len = libxl_string_list_length(&pairs);
-            for (i = 0; i < len; i++) {
-                char *key, *key_untrimmed, *value, *value_untrimmed;
-                int rc;
-                rc = split_string_into_pair(pairs[i], "=",
-                                            &key_untrimmed,
-                                            &value_untrimmed);
-                if (rc != 0) {
-                    fprintf(stderr, "failed to parse channel configuration: %s",
-                            pairs[i]);
-                    exit(1);
-                }
-                trim(isspace, key_untrimmed, &key);
-                trim(isspace, value_untrimmed, &value);
-
-                if (!strcmp(key, "backend")) {
-                    replace_string(&chn->backend_domname, value);
-                } else if (!strcmp(key, "name")) {
-                    replace_string(&chn->name, value);
-                } else if (!strcmp(key, "path")) {
-                    replace_string(&path, value);
-                } else if (!strcmp(key, "connection")) {
-                    if (!strcmp(value, "pty")) {
-                        chn->connection = LIBXL_CHANNEL_CONNECTION_PTY;
-                    } else if (!strcmp(value, "socket")) {
-                        chn->connection = LIBXL_CHANNEL_CONNECTION_SOCKET;
-                    } else {
-                        fprintf(stderr, "unknown channel connection '%s'\n",
-                                value);
-                        exit(1);
-                    }
-                } else {
-                    fprintf(stderr, "unknown channel parameter '%s',"
-                                  " ignoring\n", key);
-                }
-                free(key);
-                free(key_untrimmed);
-                free(value);
-                free(value_untrimmed);
-            }
-            switch (chn->connection) {
-            case LIBXL_CHANNEL_CONNECTION_UNKNOWN:
-                fprintf(stderr, "channel has unknown 'connection'\n");
-                exit(1);
-            case LIBXL_CHANNEL_CONNECTION_SOCKET:
-                if (!path) {
-                    fprintf(stderr, "channel connection 'socket' requires path=..\n");
-                    exit(1);
-                }
-                chn->u.socket.path = xstrdup(path);
-                break;
-            case LIBXL_CHANNEL_CONNECTION_PTY:
-                /* Nothing to do since PTY has no arguments */
-                break;
-            default:
-                fprintf(stderr, "unknown channel connection: %d",
-                        chn->connection);
-                exit(1);
-            }
-            libxl_string_list_dispose(&pairs);
-            free(path);
-        }
-    }
-
-    if (!xlu_cfg_get_list (config, "vif", &nics, 0, 0)) {
-        d_config->num_nics = 0;
-        d_config->nics = NULL;
-        while ((buf = xlu_cfg_get_listitem (nics, d_config->num_nics)) != NULL) {
-            libxl_device_nic *nic;
-            char *buf2 = strdup(buf);
-            char *p;
-
-            nic = ARRAY_EXTEND_INIT(d_config->nics,
-                                    d_config->num_nics,
-                                    libxl_device_nic_init);
-            set_default_nic_values(nic);
-
-            p = strtok(buf2, ",");
-            if (!p)
-                goto skip_nic;
-            do {
-                while (*p == ' ')
-                    p++;
-                parse_nic_config(nic, &config, p);
-            } while ((p = strtok(NULL, ",")) != NULL);
-skip_nic:
-            free(buf2);
-        }
-    }
-
-    if (!xlu_cfg_get_list(config, "vif2", NULL, 0, 0)) {
-        fprintf(stderr, "WARNING: vif2: netchannel2 is deprecated and not supported by xl\n");
-    }
-
-    d_config->num_vfbs = 0;
-    d_config->num_vkbs = 0;
-    d_config->vfbs = NULL;
-    d_config->vkbs = NULL;
-
-    if (!xlu_cfg_get_list (config, "vfb", &cvfbs, 0, 0)) {
-        while ((buf = xlu_cfg_get_listitem (cvfbs, d_config->num_vfbs)) != NULL) {
-            libxl_device_vfb *vfb;
-            libxl_device_vkb *vkb;
-
-            char *buf2 = strdup(buf);
-            char *p, *p2;
-
-            vfb = ARRAY_EXTEND_INIT(d_config->vfbs, d_config->num_vfbs,
-                                    libxl_device_vfb_init);
-
-            vkb = ARRAY_EXTEND_INIT(d_config->vkbs, d_config->num_vkbs,
-                                    libxl_device_vkb_init);
-
-            p = strtok(buf2, ",");
-            if (!p)
-                goto skip_vfb;
-            do {
-                while (*p == ' ')
-                    p++;
-                if ((p2 = strchr(p, '=')) == NULL)
-                    break;
-                *p2 = '\0';
-                if (!strcmp(p, "vnc")) {
-                    libxl_defbool_set(&vfb->vnc.enable, atoi(p2 + 1));
-                } else if (!strcmp(p, "vnclisten")) {
-                    free(vfb->vnc.listen);
-                    vfb->vnc.listen = strdup(p2 + 1);
-                } else if (!strcmp(p, "vncpasswd")) {
-                    free(vfb->vnc.passwd);
-                    vfb->vnc.passwd = strdup(p2 + 1);
-                } else if (!strcmp(p, "vncdisplay")) {
-                    vfb->vnc.display = atoi(p2 + 1);
-                } else if (!strcmp(p, "vncunused")) {
-                    libxl_defbool_set(&vfb->vnc.findunused, atoi(p2 + 1));
-                } else if (!strcmp(p, "keymap")) {
-                    free(vfb->keymap);
-                    vfb->keymap = strdup(p2 + 1);
-                } else if (!strcmp(p, "sdl")) {
-                    libxl_defbool_set(&vfb->sdl.enable, atoi(p2 + 1));
-                } else if (!strcmp(p, "opengl")) {
-                    libxl_defbool_set(&vfb->sdl.opengl, atoi(p2 + 1));
-                } else if (!strcmp(p, "display")) {
-                    free(vfb->sdl.display);
-                    vfb->sdl.display = strdup(p2 + 1);
-                } else if (!strcmp(p, "xauthority")) {
-                    free(vfb->sdl.xauthority);
-                    vfb->sdl.xauthority = strdup(p2 + 1);
-                }
-            } while ((p = strtok(NULL, ",")) != NULL);
+    return rc;
+}
 
-skip_vfb:
-            free(buf2);
-        }
-    }
+static yajl_gen_status printf_info_one_json(yajl_gen hand, int domid,
+                                            libxl_domain_config *d_config)
+{
+    yajl_gen_status s;
 
-    if (!xlu_cfg_get_long (config, "pci_msitranslate", &l, 0))
-        pci_msitranslate = l;
+    s = yajl_gen_map_open(hand);
+    if (s != yajl_gen_status_ok)
+        goto out;
 
-    if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l, 0))
-        pci_power_mgmt = l;
+    s = yajl_gen_string(hand, (const unsigned char *)"domid",
+                        sizeof("domid")-1);
+    if (s != yajl_gen_status_ok)
+        goto out;
+    if (domid != -1)
+        s = yajl_gen_integer(hand, domid);
+    else
+        s = yajl_gen_null(hand);
+    if (s != yajl_gen_status_ok)
+        goto out;
 
-    if (!xlu_cfg_get_long (config, "pci_permissive", &l, 0))
-        pci_permissive = l;
+    s = yajl_gen_string(hand, (const unsigned char *)"config",
+                        sizeof("config")-1);
+    if (s != yajl_gen_status_ok)
+        goto out;
+    s = libxl_domain_config_gen_json(hand, d_config);
+    if (s != yajl_gen_status_ok)
+        goto out;
 
-    if (!xlu_cfg_get_long (config, "pci_seize", &l, 0))
-        pci_seize = l;
+    s = yajl_gen_map_close(hand);
+    if (s != yajl_gen_status_ok)
+        goto out;
 
-    /* To be reworked (automatically enabled) once the auto ballooning
-     * after guest starts is done (with PCI devices passed in). */
-    if (c_info->type == LIBXL_DOMAIN_TYPE_PV) {
-        xlu_cfg_get_defbool(config, "e820_host", &b_info->u.pv.e820_host, 0);
-    }
+out:
+    return s;
+}
 
-    if (!xlu_cfg_get_string(config, "rdm", &buf, 0)) {
-        libxl_rdm_reserve rdm;
-        if (!xlu_rdm_parse(config, &rdm, buf)) {
-            b_info->u.hvm.rdm.strategy = rdm.strategy;
-            b_info->u.hvm.rdm.policy = rdm.policy;
-        }
-    }
+static void printf_info(enum output_format output_format,
+                        int domid,
+                        libxl_domain_config *d_config, FILE *fh)
+{
+    if (output_format == OUTPUT_FORMAT_SXP)
+        return printf_info_sexp(domid, d_config, fh);
 
-    if (!xlu_cfg_get_list (config, "pci", &pcis, 0, 0)) {
-        d_config->num_pcidevs = 0;
-        d_config->pcidevs = NULL;
-        for(i = 0; (buf = xlu_cfg_get_listitem (pcis, i)) != NULL; i++) {
-            libxl_device_pci *pcidev;
+    const char *buf;
+    libxl_yajl_length len = 0;
+    yajl_gen_status s;
+    yajl_gen hand;
 
-            pcidev = ARRAY_EXTEND_INIT_NODEVID(d_config->pcidevs,
-                                               d_config->num_pcidevs,
-                                               libxl_device_pci_init);
-            pcidev->msitranslate = pci_msitranslate;
-            pcidev->power_mgmt = pci_power_mgmt;
-            pcidev->permissive = pci_permissive;
-            pcidev->seize = pci_seize;
-            /*
-             * Like other pci option, the per-device policy always follows
-             * the global policy by default.
-             */
-            pcidev->rdm_policy = b_info->u.hvm.rdm.policy;
-            e = xlu_pci_parse_bdf(config, pcidev, buf);
-            if (e) {
-                fprintf(stderr,
-                        "unable to parse PCI BDF `%s' for passthrough\n",
-                        buf);
-                exit(-e);
-            }
-        }
-        if (d_config->num_pcidevs && c_info->type == LIBXL_DOMAIN_TYPE_PV)
-            libxl_defbool_set(&b_info->u.pv.e820_host, true);
+    hand = libxl_yajl_gen_alloc(NULL);
+    if (!hand) {
+        fprintf(stderr, "unable to allocate JSON generator\n");
+        return;
     }
 
-    if (!xlu_cfg_get_list (config, "dtdev", &dtdevs, 0, 0)) {
-        d_config->num_dtdevs = 0;
-        d_config->dtdevs = NULL;
-        for (i = 0; (buf = xlu_cfg_get_listitem(dtdevs, i)) != NULL; i++) {
-            libxl_device_dtdev *dtdev;
+    s = printf_info_one_json(hand, domid, d_config);
+    if (s != yajl_gen_status_ok)
+        goto out;
 
-            dtdev = ARRAY_EXTEND_INIT_NODEVID(d_config->dtdevs,
-                                              d_config->num_dtdevs,
-                                              libxl_device_dtdev_init);
+    s = yajl_gen_get_buf(hand, (const unsigned char **)&buf, &len);
+    if (s != yajl_gen_status_ok)
+        goto out;
 
-            dtdev->path = strdup(buf);
-            if (dtdev->path == NULL) {
-                fprintf(stderr, "unable to duplicate string for dtdevs\n");
-                exit(-1);
-            }
-        }
-    }
+    fputs(buf, fh);
 
-    if (!xlu_cfg_get_list(config, "usbctrl", &usbctrls, 0, 0)) {
-        d_config->num_usbctrls = 0;
-        d_config->usbctrls = NULL;
-        while ((buf = xlu_cfg_get_listitem(usbctrls, d_config->num_usbctrls))
-               != NULL) {
-            libxl_device_usbctrl *usbctrl;
-            char *buf2 = strdup(buf);
-            char *p;
-
-            usbctrl = ARRAY_EXTEND_INIT(d_config->usbctrls,
-                                        d_config->num_usbctrls,
-                                        libxl_device_usbctrl_init);
-            p = strtok(buf2, ",");
-            if (!p)
-                goto skip_usbctrl;
-            do {
-                while (*p == ' ')
-                    p++;
-                if (parse_usbctrl_config(usbctrl, p))
-                    exit(1);
-            } while ((p = strtok(NULL, ",")) != NULL);
-skip_usbctrl:
-            free(buf2);
-        }
-    }
-
-    if (!xlu_cfg_get_list(config, "usbdev", &usbdevs, 0, 0)) {
-        d_config->num_usbdevs = 0;
-        d_config->usbdevs = NULL;
-        while ((buf = xlu_cfg_get_listitem(usbdevs, d_config->num_usbdevs))
-               != NULL) {
-            libxl_device_usbdev *usbdev;
-            char *buf2 = strdup(buf);
-            char *p;
-
-            usbdev = ARRAY_EXTEND_INIT_NODEVID(d_config->usbdevs,
-                                               d_config->num_usbdevs,
-                                               libxl_device_usbdev_init);
-            p = strtok(buf2, ",");
-            if (!p)
-                goto skip_usbdev;
-            do {
-                while (*p == ' ')
-                    p++;
-                if (parse_usbdev_config(usbdev, p))
-                    exit(1);
-            } while ((p = strtok(NULL, ",")) != NULL);
-skip_usbdev:
-            free(buf2);
-        }
-    }
-
-    switch (xlu_cfg_get_list(config, "cpuid", &cpuids, 0, 1)) {
-    case 0:
-        {
-            const char *errstr;
-
-            for (i = 0; (buf = xlu_cfg_get_listitem(cpuids, i)) != NULL; i++) {
-                e = libxl_cpuid_parse_config_xend(&b_info->cpuid, buf);
-                switch (e) {
-                case 0: continue;
-                case 1:
-                    errstr = "illegal leaf number";
-                    break;
-                case 2:
-                    errstr = "illegal subleaf number";
-                    break;
-                case 3:
-                    errstr = "missing colon";
-                    break;
-                case 4:
-                    errstr = "invalid register name (must be e[abcd]x)";
-                    break;
-                case 5:
-                    errstr = "policy string must be exactly 32 characters long";
-                    break;
-                default:
-                    errstr = "unknown error";
-                    break;
-                }
-                fprintf(stderr, "while parsing CPUID line: \"%s\":\n", buf);
-                fprintf(stderr, "  error #%i: %s\n", e, errstr);
-            }
-        }
-        break;
-    case EINVAL:    /* config option is not a list, parse as a string */
-        if (!xlu_cfg_get_string(config, "cpuid", &buf, 0)) {
-            char *buf2, *p, *strtok_ptr = NULL;
-            const char *errstr;
-
-            buf2 = strdup(buf);
-            p = strtok_r(buf2, ",", &strtok_ptr);
-            if (p == NULL) {
-                free(buf2);
-                break;
-            }
-            if (strcmp(p, "host")) {
-                fprintf(stderr, "while parsing CPUID string: \"%s\":\n", buf);
-                fprintf(stderr, "  error: first word must be \"host\"\n");
-                free(buf2);
-                break;
-            }
-            for (p = strtok_r(NULL, ",", &strtok_ptr); p != NULL;
-                 p = strtok_r(NULL, ",", &strtok_ptr)) {
-                e = libxl_cpuid_parse_config(&b_info->cpuid, p);
-                switch (e) {
-                case 0: continue;
-                case 1:
-                    errstr = "missing \"=\" in key=value";
-                    break;
-                case 2:
-                    errstr = "unknown CPUID flag name";
-                    break;
-                case 3:
-                    errstr = "illegal CPUID value (must be: [0|1|x|k|s])";
-                    break;
-                default:
-                    errstr = "unknown error";
-                    break;
-                }
-                fprintf(stderr, "while parsing CPUID flag: \"%s\":\n", p);
-                fprintf(stderr, "  error #%i: %s\n", e, errstr);
-            }
-            free(buf2);
-        }
-        break;
-    default:
-        break;
-    }
+out:
+    yajl_gen_free(hand);
 
-    /* parse device model arguments, this works for pv, hvm and stubdom */
-    if (!xlu_cfg_get_string (config, "device_model", &buf, 0)) {
+    if (s != yajl_gen_status_ok)
         fprintf(stderr,
-                "WARNING: ignoring device_model directive.\n"
-                "WARNING: Use \"device_model_override\" instead if you"
-                " really want a non-default device_model\n");
-        if (strstr(buf, "stubdom-dm")) {
-            if (c_info->type == LIBXL_DOMAIN_TYPE_HVM)
-                fprintf(stderr, "WARNING: Or use"
-                        " \"device_model_stubdomain_override\" if you "
-                        " want to enable stubdomains\n");
-            else
-                fprintf(stderr, "WARNING: ignoring"
-                        " \"device_model_stubdomain_override\" directive"
-                        " for pv guest\n");
-        }
-    }
+                "unable to format domain config as JSON (YAJL:%d)\n", s);
 
+    xflush_stream(fh);
+}
 
-    xlu_cfg_replace_string (config, "device_model_override",
-                            &b_info->device_model, 0);
-    if (!xlu_cfg_get_string (config, "device_model_version", &buf, 0)) {
-        if (!strcmp(buf, "qemu-xen-traditional")) {
-            b_info->device_model_version
-                = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL;
-        } else if (!strcmp(buf, "qemu-xen")) {
-            b_info->device_model_version
-                = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN;
-        } else if (!strcmp(buf, "none")) {
-            b_info->device_model_version = LIBXL_DEVICE_MODEL_VERSION_NONE;
-        } else {
-            fprintf(stderr,
-                    "Unknown device_model_version \"%s\" specified\n", buf);
-            exit(1);
-        }
-    } else if (b_info->device_model)
-        fprintf(stderr, "WARNING: device model override given without specific DM version\n");
-    xlu_cfg_get_defbool (config, "device_model_stubdomain_override",
-                         &b_info->device_model_stubdomain, 0);
+static int do_daemonize(char *name, const char *pidfile)
+{
+    char *fullname;
+    pid_t child1;
+    int nullfd, ret = 0;
 
-    if (!xlu_cfg_get_string (config, "device_model_stubdomain_seclabel",
-                             &buf, 0))
-        xlu_cfg_replace_string(config, "device_model_stubdomain_seclabel",
-                               &b_info->device_model_ssid_label, 0);
+    child1 = xl_fork(child_waitdaemon, "domain monitoring daemonizing child");
+    if (child1) {
+        ret = child_report(child_waitdaemon);
+        if (ret) goto out;
+        ret = 1;
+        goto out;
+    }
 
-    xlu_cfg_replace_string(config, "device_model_user",
-                           &b_info->device_model_user, 0);
+    postfork();
 
-#define parse_extra_args(type)                                            \
-    e = xlu_cfg_get_list_as_string_list(config, "device_model_args"#type, \
-                                    &b_info->extra##type, 0);            \
-    if (e && e != ESRCH) {                                                \
-        fprintf(stderr,"xl: Unable to parse device_model_args"#type".\n");\
-        exit(-ERROR_FAIL);                                                \
+    ret = libxl_create_logfile(ctx, name, &fullname);
+    if (ret) {
+        LOG("failed to open logfile %s: %s",fullname,strerror(errno));
+        exit(-1);
     }
 
-    /* parse extra args for qemu, common to both pv, hvm */
-    parse_extra_args();
-
-    /* parse extra args dedicated to pv */
-    parse_extra_args(_pv);
+    CHK_SYSCALL(logfile = open(fullname, O_WRONLY|O_CREAT|O_APPEND, 0644));
+    free(fullname);
+    assert(logfile >= 3);
 
-    /* parse extra args dedicated to hvm */
-    parse_extra_args(_hvm);
+    CHK_SYSCALL(nullfd = open("/dev/null", O_RDONLY));
+    assert(nullfd >= 3);
 
-#undef parse_extra_args
+    dup2(nullfd, 0);
+    dup2(logfile, 1);
+    dup2(logfile, 2);
 
-    /* If we've already got vfb=[] for PV guest then ignore top level
-     * VNC config. */
-    if (c_info->type == LIBXL_DOMAIN_TYPE_PV && !d_config->num_vfbs) {
-        long vnc_enabled = 0;
+    close(nullfd);
 
-        if (!xlu_cfg_get_long (config, "vnc", &l, 0))
-            vnc_enabled = l;
+    CHK_SYSCALL(daemon(0, 1));
 
-        if (vnc_enabled) {
-            libxl_device_vfb *vfb;
-            libxl_device_vkb *vkb;
+    if (pidfile) {
+        int fd = open(pidfile, O_RDWR | O_CREAT, S_IRUSR|S_IWUSR);
+        char *pid = NULL;
 
-            vfb = ARRAY_EXTEND_INIT(d_config->vfbs, d_config->num_vfbs,
-                                    libxl_device_vfb_init);
+        if (fd == -1) {
+            perror("Unable to open pidfile");
+            exit(1);
+        }
 
-            vkb = ARRAY_EXTEND_INIT(d_config->vkbs, d_config->num_vkbs,
-                                    libxl_device_vkb_init);
+        if (asprintf(&pid, "%ld\n", (long)getpid()) == -1) {
+            perror("Formatting pid");
+            exit(1);
+        }
 
-            parse_top_level_vnc_options(config, &vfb->vnc);
-            parse_top_level_sdl_options(config, &vfb->sdl);
-            xlu_cfg_replace_string (config, "keymap", &vfb->keymap, 0);
+        if (write(fd, pid, strlen(pid)) < 0) {
+            perror("Writing pid");
+            exit(1);
         }
-    } else {
-        parse_top_level_vnc_options(config, &b_info->u.hvm.vnc);
-        parse_top_level_sdl_options(config, &b_info->u.hvm.sdl);
-    }
-
-    if (c_info->type == LIBXL_DOMAIN_TYPE_HVM) {
-        if (!xlu_cfg_get_string (config, "vga", &buf, 0)) {
-            if (!strcmp(buf, "stdvga")) {
-                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_STD;
-            } else if (!strcmp(buf, "cirrus")) {
-                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
-            } else if (!strcmp(buf, "none")) {
-                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_NONE;
-            } else if (!strcmp(buf, "qxl")) {
-                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_QXL;
-            } else {
-                fprintf(stderr, "Unknown vga \"%s\" specified\n", buf);
-                exit(1);
-            }
-        } else if (!xlu_cfg_get_long(config, "stdvga", &l, 0))
-            b_info->u.hvm.vga.kind = l ? LIBXL_VGA_INTERFACE_TYPE_STD :
-                                         LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
-
-        if (!xlu_cfg_get_string(config, "hdtype", &buf, 0) &&
-            libxl_hdtype_from_string(buf, &b_info->u.hvm.hdtype)) {
-                fprintf(stderr, "ERROR: invalid value \"%s\" for \"hdtype\"\n",
-                    buf);
-                exit (1);
-        }
-
-        xlu_cfg_replace_string (config, "keymap", &b_info->u.hvm.keymap, 0);
-        xlu_cfg_get_defbool (config, "spice", &b_info->u.hvm.spice.enable, 0);
-        if (!xlu_cfg_get_long (config, "spiceport", &l, 0))
-            b_info->u.hvm.spice.port = l;
-        if (!xlu_cfg_get_long (config, "spicetls_port", &l, 0))
-            b_info->u.hvm.spice.tls_port = l;
-        xlu_cfg_replace_string (config, "spicehost",
-                                &b_info->u.hvm.spice.host, 0);
-        xlu_cfg_get_defbool(config, "spicedisable_ticketing",
-                            &b_info->u.hvm.spice.disable_ticketing, 0);
-        xlu_cfg_replace_string (config, "spicepasswd",
-                                &b_info->u.hvm.spice.passwd, 0);
-        xlu_cfg_get_defbool(config, "spiceagent_mouse",
-                            &b_info->u.hvm.spice.agent_mouse, 0);
-        xlu_cfg_get_defbool(config, "spicevdagent",
-                            &b_info->u.hvm.spice.vdagent, 0);
-        xlu_cfg_get_defbool(config, "spice_clipboard_sharing",
-                            &b_info->u.hvm.spice.clipboard_sharing, 0);
-        if (!xlu_cfg_get_long (config, "spiceusbredirection", &l, 0))
-            b_info->u.hvm.spice.usbredirection = l;
-        xlu_cfg_replace_string (config, "spice_image_compression",
-                                &b_info->u.hvm.spice.image_compression, 0);
-        xlu_cfg_replace_string (config, "spice_streaming_video",
-                                &b_info->u.hvm.spice.streaming_video, 0);
-        xlu_cfg_get_defbool(config, "nographic", &b_info->u.hvm.nographic, 0);
-        if (!xlu_cfg_get_long(config, "gfx_passthru", &l, 1)) {
-            libxl_defbool_set(&b_info->u.hvm.gfx_passthru, l);
-        } else if (!xlu_cfg_get_string(config, "gfx_passthru", &buf, 0)) {
-            if (libxl_gfx_passthru_kind_from_string(buf,
-                                        &b_info->u.hvm.gfx_passthru_kind)) {
-                fprintf(stderr,
-                        "ERROR: invalid value \"%s\" for \"gfx_passthru\"\n",
-                        buf);
-                exit (1);
-            }
-            libxl_defbool_set(&b_info->u.hvm.gfx_passthru, true);
-        }
-        switch (xlu_cfg_get_list_as_string_list(config, "serial",
-                                                &b_info->u.hvm.serial_list,
-                                                1))
-        {
-
-        case 0: break; /* Success */
-        case ESRCH: break; /* Option not present */
-        case EINVAL:
-            /* If it's not a valid list, try reading it as an atom,
-             * falling through to an error if it fails */
-            if (!xlu_cfg_replace_string(config, "serial",
-                                        &b_info->u.hvm.serial, 0))
-                break;
-            /* FALLTHRU */
-        default:
-            fprintf(stderr,"xl: Unable to parse serial.\n");
-            exit(-ERROR_FAIL);
-        }
-        xlu_cfg_replace_string (config, "boot", &b_info->u.hvm.boot, 0);
-        xlu_cfg_get_defbool(config, "usb", &b_info->u.hvm.usb, 0);
-        if (!xlu_cfg_get_long (config, "usbversion", &l, 0))
-            b_info->u.hvm.usbversion = l;
-        switch (xlu_cfg_get_list_as_string_list(config, "usbdevice",
-                                                &b_info->u.hvm.usbdevice_list,
-                                                1))
-        {
-
-        case 0: break; /* Success */
-        case ESRCH: break; /* Option not present */
-        case EINVAL:
-            /* If it's not a valid list, try reading it as an atom,
-             * falling through to an error if it fails */
-            if (!xlu_cfg_replace_string(config, "usbdevice",
-                                        &b_info->u.hvm.usbdevice, 0))
-                break;
-            /* FALLTHRU */
-        default:
-            fprintf(stderr,"xl: Unable to parse usbdevice.\n");
-            exit(-ERROR_FAIL);
+
+        if (close(fd) < 0) {
+            perror("Closing pidfile");
+            exit(1);
         }
-        xlu_cfg_replace_string (config, "soundhw", &b_info->u.hvm.soundhw, 0);
-        xlu_cfg_get_defbool(config, "xen_platform_pci",
-                            &b_info->u.hvm.xen_platform_pci, 0);
 
-        if(b_info->u.hvm.vnc.listen
-           && b_info->u.hvm.vnc.display
-           && strchr(b_info->u.hvm.vnc.listen, ':') != NULL) {
-            fprintf(stderr,
-                    "ERROR: Display specified both in vnclisten"
-                    " and vncdisplay!\n");
-            exit (1);
+        free(pid);
+    }
 
-        }
+out:
+    return ret;
+}
 
-        if (!xlu_cfg_get_string (config, "vendor_device", &buf, 0)) {
-            libxl_vendor_device d;
+void set_default_nic_values(libxl_device_nic *nic);
+void set_default_nic_values(libxl_device_nic *nic)
+{
 
-            e = libxl_vendor_device_from_string(buf, &d);
-            if (e) {
-                fprintf(stderr,
-                        "xl: unknown vendor_device '%s'\n",
-                        buf);
-                exit(-ERROR_FAIL);
-            }
+    if (default_vifscript) {
+        free(nic->script);
+        nic->script = strdup(default_vifscript);
+    }
 
-            b_info->u.hvm.vendor_device = d;
-        }
+    if (default_bridge) {
+        free(nic->bridge);
+        nic->bridge = strdup(default_bridge);
     }
 
-    if (!xlu_cfg_get_string (config, "gic_version", &buf, 1)) {
-        e = libxl_gic_version_from_string(buf, &b_info->arch_arm.gic_version);
-        if (e) {
-            fprintf(stderr,
-                    "Unknown gic_version \"%s\" specified\n", buf);
-            exit(-ERROR_FAIL);
-        }
-     }
+    if (default_gatewaydev) {
+        free(nic->gatewaydev);
+        nic->gatewaydev = strdup(default_gatewaydev);
+    }
 
-    xlu_cfg_destroy(config);
+    if (default_vifbackend) {
+        free(nic->backend_domname);
+        nic->backend_domname = strdup(default_vifbackend);
+    }
 }
 
 static void reload_domain_config(uint32_t domid,
@@ -2442,7 +463,7 @@ static domain_restart_type handle_domain_death(uint32_t *r_domid,
 
     LOG("Action for shutdown reason code %d is %s",
         event->u.domain_shutdown.shutdown_reason,
-        action_on_shutdown_names[action]);
+        get_action_on_shutdown_name(action));
 
     if (action == LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY || action == LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_RESTART) {
         char *corefile;
@@ -3149,40 +1170,6 @@ void help(const char *command)
     }
 }
 
-/* Returns -1 on failure; the amount of memory on success. */
-static int64_t parse_mem_size_kb(const char *mem)
-{
-    char *endptr;
-    int64_t kbytes;
-
-    kbytes = strtoll(mem, &endptr, 10);
-
-    if (strlen(endptr) > 1)
-        return -1;
-
-    switch (tolower((uint8_t)*endptr)) {
-    case 't':
-        kbytes <<= 10;
-        /* fallthrough */
-    case 'g':
-        kbytes <<= 10;
-        /* fallthrough */
-    case '\0':
-    case 'm':
-        kbytes <<= 10;
-        /* fallthrough */
-    case 'k':
-        break;
-    case 'b':
-        kbytes >>= 10;
-        break;
-    default:
-        return -1;
-    }
-
-    return kbytes;
-}
-
 static int set_memory_max(uint32_t domid, const char *mem)
 {
     int64_t memorykb;
@@ -5522,7 +3509,7 @@ int main_vcpupin(int argc, char **argv)
      */
     if (!strcmp(hard_str, "-"))
         hard = NULL;
-    else if (cpurange_parse(hard_str, hard))
+    else if (parse_cpurange(hard_str, hard))
         goto out;
     /*
      * Soft affinity is handled similarly. Only difference: we also want
@@ -5530,7 +3517,7 @@ int main_vcpupin(int argc, char **argv)
      */
     if (argc <= optind+3 || !strcmp(soft_str, "-"))
         soft = NULL;
-    else if (cpurange_parse(soft_str, soft))
+    else if (parse_cpurange(soft_str, soft))
         goto out;
 
     if (dryrun_only) {
@@ -7794,7 +5781,7 @@ int main_cpupoolcreate(int argc, char **argv)
             n_cpus++;
         }
     } else if (!xlu_cfg_get_string(config, "cpus", &buf, 0)) {
-        if (cpurange_parse(buf, &cpumap))
+        if (parse_cpurange(buf, &cpumap))
             goto out_cfg;
 
         n_cpus = 0;
@@ -7975,7 +5962,7 @@ int main_cpupoolcpuadd(int argc, char **argv)
     }
 
     pool = argv[optind++];
-    if (cpurange_parse(argv[optind], &cpumap))
+    if (parse_cpurange(argv[optind], &cpumap))
         goto out;
 
     if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
@@ -8013,7 +6000,7 @@ int main_cpupoolcpuremove(int argc, char **argv)
     }
 
     pool = argv[optind++];
-    if (cpurange_parse(argv[optind], &cpumap))
+    if (parse_cpurange(argv[optind], &cpumap))
         goto out;
 
     if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
new file mode 100644
index 0000000000..1ef0c272a8
--- /dev/null
+++ b/tools/xl/xl_parse.c
@@ -0,0 +1,2052 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <ctype.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <xen/hvm/e820.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+extern void set_default_nic_values(libxl_device_nic *nic);
+
+#define ARRAY_EXTEND_INIT__CORE(array,count,initfn,more)                \
+    ({                                                                  \
+        typeof((count)) array_extend_old_count = (count);               \
+        (count)++;                                                      \
+        (array) = xrealloc((array), sizeof(*array) * (count));          \
+        (initfn)(&(array)[array_extend_old_count]);                     \
+        more;                                                           \
+        &(array)[array_extend_old_count];                               \
+    })
+
+#define ARRAY_EXTEND_INIT(array,count,initfn)                           \
+    ARRAY_EXTEND_INIT__CORE((array),(count),(initfn), ({                \
+        (array)[array_extend_old_count].devid = array_extend_old_count; \
+        }))
+
+#define ARRAY_EXTEND_INIT_NODEVID(array,count,initfn) \
+    ARRAY_EXTEND_INIT__CORE((array),(count),(initfn), /* nothing */ )
+
+static const char *action_on_shutdown_names[] = {
+    [LIBXL_ACTION_ON_SHUTDOWN_DESTROY] = "destroy",
+
+    [LIBXL_ACTION_ON_SHUTDOWN_RESTART] = "restart",
+    [LIBXL_ACTION_ON_SHUTDOWN_RESTART_RENAME] = "rename-restart",
+
+    [LIBXL_ACTION_ON_SHUTDOWN_PRESERVE] = "preserve",
+
+    [LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY] = "coredump-destroy",
+    [LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_RESTART] = "coredump-restart",
+
+    [LIBXL_ACTION_ON_SHUTDOWN_SOFT_RESET] = "soft-reset",
+};
+
+const char *get_action_on_shutdown_name(libxl_action_on_shutdown a)
+{
+    return action_on_shutdown_names[a];
+}
+
+static int parse_action_on_shutdown(const char *buf, libxl_action_on_shutdown *a)
+{
+    int i;
+    const char *n;
+
+    for (i = 0; i < sizeof(action_on_shutdown_names) / sizeof(action_on_shutdown_names[0]); i++) {
+        n = action_on_shutdown_names[i];
+
+        if (!n) continue;
+
+        if (strcmp(buf, n) == 0) {
+            *a = i;
+            return 1;
+        }
+    }
+    return 0;
+}
+
+#define DSTATE_INITIAL   0
+#define DSTATE_TAP       1
+#define DSTATE_PHYSPATH  2
+#define DSTATE_VIRTPATH  3
+#define DSTATE_VIRTTYPE  4
+#define DSTATE_RW        5
+#define DSTATE_TERMINAL  6
+
+void parse_disk_config_multistring(XLU_Config **config,
+                                   int nspecs, const char *const *specs,
+                                   libxl_device_disk *disk)
+{
+    int e;
+
+    libxl_device_disk_init(disk);
+
+    if (!*config) {
+        *config = xlu_cfg_init(stderr, "command line");
+        if (!*config) { perror("xlu_cfg_init"); exit(-1); }
+    }
+
+    e = xlu_disk_parse(*config, nspecs, specs, disk);
+    if (e == EINVAL) exit(EXIT_FAILURE);
+    if (e) {
+        fprintf(stderr,"xlu_disk_parse failed: %s\n",strerror(errno));
+        exit(EXIT_FAILURE);
+    }
+}
+
+void parse_disk_config(XLU_Config **config, const char *spec,
+                       libxl_device_disk *disk)
+{
+    parse_disk_config_multistring(config, 1, &spec, disk);
+}
+
+static void parse_vif_rate(XLU_Config **config, const char *rate,
+                           libxl_device_nic *nic)
+{
+    int e;
+
+    e = xlu_vif_parse_rate(*config, rate, nic);
+    if (e == EINVAL || e == EOVERFLOW) exit(EXIT_FAILURE);
+    if (e) {
+        fprintf(stderr,"xlu_vif_parse_rate failed: %s\n",strerror(errno));
+        exit(EXIT_FAILURE);
+    }
+}
+
+int parse_range(const char *str, unsigned long *a, unsigned long *b)
+{
+    const char *nstr;
+    char *endptr;
+
+    *a = *b = strtoul(str, &endptr, 10);
+    if (endptr == str || *a == ULONG_MAX)
+        return 1;
+
+    if (*endptr == '-') {
+        nstr = endptr + 1;
+
+        *b = strtoul(nstr, &endptr, 10);
+        if (endptr == nstr || *b == ULONG_MAX || *b < *a)
+            return 1;
+    }
+
+    /* Valid value or range so far, but we also don't want junk after that */
+    if (*endptr != '\0')
+        return 1;
+
+    return 0;
+}
+
+/*
+ * Add or removes a specific set of cpus (specified in str, either as
+ * single cpus or as entire NUMA nodes) to/from cpumap.
+ */
+static int update_cpumap_range(const char *str, libxl_bitmap *cpumap)
+{
+    unsigned long ida, idb;
+    libxl_bitmap node_cpumap;
+    bool is_not = false, is_nodes = false;
+    int rc = 0;
+
+    libxl_bitmap_init(&node_cpumap);
+
+    rc = libxl_node_bitmap_alloc(ctx, &node_cpumap, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_node_bitmap_alloc failed.\n");
+        goto out;
+    }
+
+    /* Are we adding or removing cpus/nodes? */
+    if (STR_SKIP_PREFIX(str, "^")) {
+        is_not = true;
+    }
+
+    /* Are we dealing with cpus or full nodes? */
+    if (STR_SKIP_PREFIX(str, "node:") || STR_SKIP_PREFIX(str, "nodes:")) {
+        is_nodes = true;
+    }
+
+    if (strcmp(str, "all") == 0) {
+        /* We do not accept "^all" or "^nodes:all" */
+        if (is_not) {
+            fprintf(stderr, "Can't combine \"^\" and \"all\".\n");
+            rc = ERROR_INVAL;
+        } else
+            libxl_bitmap_set_any(cpumap);
+        goto out;
+    }
+
+    rc = parse_range(str, &ida, &idb);
+    if (rc) {
+        fprintf(stderr, "Invalid pcpu range: %s.\n", str);
+        goto out;
+    }
+
+    /* Add or remove the specified cpus in the range */
+    while (ida <= idb) {
+        if (is_nodes) {
+            /* Add/Remove all the cpus of a NUMA node */
+            int i;
+
+            rc = libxl_node_to_cpumap(ctx, ida, &node_cpumap);
+            if (rc) {
+                fprintf(stderr, "libxl_node_to_cpumap failed.\n");
+                goto out;
+            }
+
+            /* Add/Remove all the cpus in the node cpumap */
+            libxl_for_each_set_bit(i, node_cpumap) {
+                is_not ? libxl_bitmap_reset(cpumap, i) :
+                         libxl_bitmap_set(cpumap, i);
+            }
+        } else {
+            /* Add/Remove this cpu */
+            is_not ? libxl_bitmap_reset(cpumap, ida) :
+                     libxl_bitmap_set(cpumap, ida);
+        }
+        ida++;
+    }
+
+ out:
+    libxl_bitmap_dispose(&node_cpumap);
+    return rc;
+}
+
+/*
+ * Takes a string representing a set of cpus (specified either as
+ * single cpus or as eintire NUMA nodes) and turns it into the
+ * corresponding libxl_bitmap (in cpumap).
+ */
+int parse_cpurange(const char *cpu, libxl_bitmap *cpumap)
+{
+    char *ptr, *saveptr = NULL, *buf = xstrdup(cpu);
+    int rc = 0;
+
+    for (ptr = strtok_r(buf, ",", &saveptr); ptr;
+         ptr = strtok_r(NULL, ",", &saveptr)) {
+        rc = update_cpumap_range(ptr, cpumap);
+        if (rc)
+            break;
+    }
+    free(buf);
+
+    return rc;
+}
+
+static void parse_top_level_vnc_options(XLU_Config *config,
+                                        libxl_vnc_info *vnc)
+{
+    long l;
+
+    xlu_cfg_get_defbool(config, "vnc", &vnc->enable, 0);
+    xlu_cfg_replace_string (config, "vnclisten", &vnc->listen, 0);
+    xlu_cfg_replace_string (config, "vncpasswd", &vnc->passwd, 0);
+    if (!xlu_cfg_get_long (config, "vncdisplay", &l, 0))
+        vnc->display = l;
+    xlu_cfg_get_defbool(config, "vncunused", &vnc->findunused, 0);
+}
+
+static void parse_top_level_sdl_options(XLU_Config *config,
+                                        libxl_sdl_info *sdl)
+{
+    xlu_cfg_get_defbool(config, "sdl", &sdl->enable, 0);
+    xlu_cfg_get_defbool(config, "opengl", &sdl->opengl, 0);
+    xlu_cfg_replace_string (config, "display", &sdl->display, 0);
+    xlu_cfg_replace_string (config, "xauthority", &sdl->xauthority, 0);
+}
+
+static char *parse_cmdline(XLU_Config *config)
+{
+    char *cmdline = NULL;
+    const char *root = NULL, *extra = NULL, *buf = NULL;
+
+    xlu_cfg_get_string (config, "cmdline", &buf, 0);
+    xlu_cfg_get_string (config, "root", &root, 0);
+    xlu_cfg_get_string (config, "extra", &extra, 0);
+
+    if (buf) {
+        cmdline = strdup(buf);
+        if (root || extra)
+            fprintf(stderr, "Warning: ignoring root= and extra= "
+                    "in favour of cmdline=\n");
+    } else {
+        if (root && extra) {
+            xasprintf(&cmdline, "root=%s %s", root, extra);
+        } else if (root) {
+            xasprintf(&cmdline, "root=%s", root);
+        } else if (extra) {
+            cmdline = strdup(extra);
+        }
+    }
+
+    if ((buf || root || extra) && !cmdline) {
+        fprintf(stderr, "Failed to allocate memory for cmdline\n");
+        exit(EXIT_FAILURE);
+    }
+
+    return cmdline;
+}
+
+static void parse_vcpu_affinity(libxl_domain_build_info *b_info,
+                                XLU_ConfigList *cpus, const char *buf,
+                                int num_cpus, bool is_hard)
+{
+    libxl_bitmap *vcpu_affinity_array;
+
+    /*
+     * If we are here, and buf is !NULL, we're dealing with a string. What
+     * we do in this case is parse it, and copy the result in _all_ (up to
+     * b_info->max_vcpus) the elements of the vcpu affinity array.
+     *
+     * If buf is NULL, we have a list, and what we do is putting in the
+     * i-eth element of the vcpu affinity array the result of the parsing
+     * of the i-eth entry of the list. If there are more vcpus than
+     * entries, it is fine to just not touch the last array elements.
+     */
+
+    /* Silently ignore values corresponding to non existing vcpus */
+    if (buf || num_cpus > b_info->max_vcpus)
+        num_cpus = b_info->max_vcpus;
+
+    if (is_hard) {
+        b_info->num_vcpu_hard_affinity = num_cpus;
+        b_info->vcpu_hard_affinity = xmalloc(num_cpus * sizeof(libxl_bitmap));
+        vcpu_affinity_array = b_info->vcpu_hard_affinity;
+    } else {
+        b_info->num_vcpu_soft_affinity = num_cpus;
+        b_info->vcpu_soft_affinity = xmalloc(num_cpus * sizeof(libxl_bitmap));
+        vcpu_affinity_array = b_info->vcpu_soft_affinity;
+    }
+
+    if (!buf) {
+        int j = 0;
+
+        while ((buf = xlu_cfg_get_listitem(cpus, j)) != NULL && j < num_cpus) {
+            libxl_bitmap_init(&vcpu_affinity_array[j]);
+            if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[j], 0)) {
+                fprintf(stderr, "Unable to allocate cpumap for vcpu %d\n", j);
+                exit(EXIT_FAILURE);
+            }
+
+            if (parse_cpurange(buf, &vcpu_affinity_array[j]))
+                exit(EXIT_FAILURE);
+
+            j++;
+        }
+
+        /* We have a list of cpumaps, disable automatic placement */
+        libxl_defbool_set(&b_info->numa_placement, false);
+    } else {
+        int i;
+
+        libxl_bitmap_init(&vcpu_affinity_array[0]);
+        if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[0], 0)) {
+            fprintf(stderr, "Unable to allocate cpumap for vcpu 0\n");
+            exit(EXIT_FAILURE);
+        }
+
+        if (parse_cpurange(buf, &vcpu_affinity_array[0]))
+            exit(EXIT_FAILURE);
+
+        for (i = 1; i < b_info->max_vcpus; i++) {
+            libxl_bitmap_init(&vcpu_affinity_array[i]);
+            if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[i], 0)) {
+                fprintf(stderr, "Unable to allocate cpumap for vcpu %d\n", i);
+                exit(EXIT_FAILURE);
+            }
+            libxl_bitmap_copy(ctx, &vcpu_affinity_array[i],
+                              &vcpu_affinity_array[0]);
+        }
+
+        libxl_defbool_set(&b_info->numa_placement, false);
+    }
+}
+
+static unsigned long parse_ulong(const char *str)
+{
+    char *endptr;
+    unsigned long val;
+
+    val = strtoul(str, &endptr, 10);
+    if (endptr == str || val == ULONG_MAX) {
+        fprintf(stderr, "xl: failed to convert \"%s\" to number\n", str);
+        exit(EXIT_FAILURE);
+    }
+    return val;
+}
+
+void replace_string(char **str, const char *val)
+{
+    free(*str);
+    *str = xstrdup(val);
+}
+
+int match_option_size(const char *prefix, size_t len,
+                      char *arg, char **argopt)
+{
+    int rc = strncmp(prefix, arg, len);
+    if (!rc) *argopt = arg+len;
+    return !rc;
+}
+
+/* Parses network data and adds info into nic
+ * Returns 1 if the input token does not match one of the keys
+ * or parsed values are not correct. Successful parse returns 0 */
+int parse_nic_config(libxl_device_nic *nic, XLU_Config **config, char *token)
+{
+    char *endptr, *oparg;
+    int i;
+    unsigned int val;
+
+    if (MATCH_OPTION("type", token, oparg)) {
+        if (!strcmp("vif", oparg)) {
+            nic->nictype = LIBXL_NIC_TYPE_VIF;
+        } else if (!strcmp("ioemu", oparg)) {
+            nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU;
+        } else {
+            fprintf(stderr, "Invalid parameter `type'.\n");
+            return 1;
+        }
+    } else if (MATCH_OPTION("mac", token, oparg)) {
+        for (i = 0; i < 6; i++) {
+            val = strtoul(oparg, &endptr, 16);
+            if ((oparg == endptr) || (val > 255)) {
+                fprintf(stderr, "Invalid parameter `mac'.\n");
+                return 1;
+            }
+            nic->mac[i] = val;
+            oparg = endptr + 1;
+        }
+    } else if (MATCH_OPTION("bridge", token, oparg)) {
+        replace_string(&nic->bridge, oparg);
+    } else if (MATCH_OPTION("netdev", token, oparg)) {
+        fprintf(stderr, "the netdev parameter is deprecated, "
+                        "please use gatewaydev instead\n");
+        replace_string(&nic->gatewaydev, oparg);
+    } else if (MATCH_OPTION("gatewaydev", token, oparg)) {
+        replace_string(&nic->gatewaydev, oparg);
+    } else if (MATCH_OPTION("ip", token, oparg)) {
+        replace_string(&nic->ip, oparg);
+    } else if (MATCH_OPTION("script", token, oparg)) {
+        replace_string(&nic->script, oparg);
+    } else if (MATCH_OPTION("backend", token, oparg)) {
+        replace_string(&nic->backend_domname, oparg);
+    } else if (MATCH_OPTION("vifname", token, oparg)) {
+        replace_string(&nic->ifname, oparg);
+    } else if (MATCH_OPTION("model", token, oparg)) {
+        replace_string(&nic->model, oparg);
+    } else if (MATCH_OPTION("rate", token, oparg)) {
+        parse_vif_rate(config, oparg, nic);
+    } else if (MATCH_OPTION("forwarddev", token, oparg)) {
+        replace_string(&nic->coloft_forwarddev, oparg);
+    } else if (MATCH_OPTION("accel", token, oparg)) {
+        fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
+    } else if (MATCH_OPTION("devid", token, oparg)) {
+        nic->devid = parse_ulong(oparg);
+    } else {
+        fprintf(stderr, "unrecognized argument `%s'\n", token);
+        return 1;
+    }
+    return 0;
+}
+
+static void parse_vnuma_config(const XLU_Config *config,
+                               libxl_domain_build_info *b_info)
+{
+    libxl_physinfo physinfo;
+    uint32_t nr_nodes;
+    XLU_ConfigList *vnuma;
+    int i, j, len, num_vnuma;
+    unsigned long max_vcpus = 0, max_memkb = 0;
+    /* Temporary storage for parsed vcpus information to avoid
+     * parsing config twice. This array has num_vnuma elements.
+     */
+    libxl_bitmap *vcpu_parsed;
+
+    libxl_physinfo_init(&physinfo);
+    if (libxl_get_physinfo(ctx, &physinfo) != 0) {
+        libxl_physinfo_dispose(&physinfo);
+        fprintf(stderr, "libxl_get_physinfo failed\n");
+        exit(EXIT_FAILURE);
+    }
+
+    nr_nodes = physinfo.nr_nodes;
+    libxl_physinfo_dispose(&physinfo);
+
+    if (xlu_cfg_get_list(config, "vnuma", &vnuma, &num_vnuma, 1))
+        return;
+
+    if (!num_vnuma)
+        return;
+
+    b_info->num_vnuma_nodes = num_vnuma;
+    b_info->vnuma_nodes = xcalloc(num_vnuma, sizeof(libxl_vnode_info));
+    vcpu_parsed = xcalloc(num_vnuma, sizeof(libxl_bitmap));
+    for (i = 0; i < num_vnuma; i++) {
+        libxl_bitmap_init(&vcpu_parsed[i]);
+        if (libxl_cpu_bitmap_alloc(ctx, &vcpu_parsed[i], b_info->max_vcpus)) {
+            fprintf(stderr, "libxl_node_bitmap_alloc failed.\n");
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    for (i = 0; i < b_info->num_vnuma_nodes; i++) {
+        libxl_vnode_info *p = &b_info->vnuma_nodes[i];
+
+        libxl_vnode_info_init(p);
+        p->distances = xcalloc(b_info->num_vnuma_nodes,
+                               sizeof(*p->distances));
+        p->num_distances = b_info->num_vnuma_nodes;
+    }
+
+    for (i = 0; i < num_vnuma; i++) {
+        XLU_ConfigValue *vnode_spec, *conf_option;
+        XLU_ConfigList *vnode_config_list;
+        int conf_count;
+        libxl_vnode_info *p = &b_info->vnuma_nodes[i];
+
+        vnode_spec = xlu_cfg_get_listitem2(vnuma, i);
+        assert(vnode_spec);
+
+        xlu_cfg_value_get_list(config, vnode_spec, &vnode_config_list, 0);
+        if (!vnode_config_list) {
+            fprintf(stderr, "xl: cannot get vnode config option list\n");
+            exit(EXIT_FAILURE);
+        }
+
+        for (conf_count = 0;
+             (conf_option =
+              xlu_cfg_get_listitem2(vnode_config_list, conf_count));
+             conf_count++) {
+
+            if (xlu_cfg_value_type(conf_option) == XLU_STRING) {
+                char *buf, *option_untrimmed, *value_untrimmed;
+                char *option, *value;
+                unsigned long val;
+
+                xlu_cfg_value_get_string(config, conf_option, &buf, 0);
+
+                if (!buf) continue;
+
+                if (split_string_into_pair(buf, "=",
+                                           &option_untrimmed,
+                                           &value_untrimmed)) {
+                    fprintf(stderr, "xl: failed to split \"%s\" into pair\n",
+                            buf);
+                    exit(EXIT_FAILURE);
+                }
+                trim(isspace, option_untrimmed, &option);
+                trim(isspace, value_untrimmed, &value);
+
+                if (!strcmp("pnode", option)) {
+                    val = parse_ulong(value);
+                    if (val >= nr_nodes) {
+                        fprintf(stderr,
+                                "xl: invalid pnode number: %lu\n", val);
+                        exit(EXIT_FAILURE);
+                    }
+                    p->pnode = val;
+                    libxl_defbool_set(&b_info->numa_placement, false);
+                } else if (!strcmp("size", option)) {
+                    val = parse_ulong(value);
+                    p->memkb = val << 10;
+                    max_memkb += p->memkb;
+                } else if (!strcmp("vcpus", option)) {
+                    libxl_string_list cpu_spec_list;
+                    unsigned long s, e;
+
+                    split_string_into_string_list(value, ",", &cpu_spec_list);
+                    len = libxl_string_list_length(&cpu_spec_list);
+
+                    for (j = 0; j < len; j++) {
+                        parse_range(cpu_spec_list[j], &s, &e);
+                        for (; s <= e; s++) {
+                            /*
+                             * Note that if we try to set a bit beyond
+                             * the size of bitmap, libxl_bitmap_set
+                             * has no effect. The resulted bitmap
+                             * doesn't reflect what user wants. The
+                             * fallout is dealt with later after
+                             * parsing.
+                             */
+                            libxl_bitmap_set(&vcpu_parsed[i], s);
+                            max_vcpus++;
+                        }
+                    }
+
+                    libxl_string_list_dispose(&cpu_spec_list);
+                } else if (!strcmp("vdistances", option)) {
+                    libxl_string_list vdist;
+
+                    split_string_into_string_list(value, ",", &vdist);
+                    len = libxl_string_list_length(&vdist);
+
+                    for (j = 0; j < len; j++) {
+                        val = parse_ulong(vdist[j]);
+                        p->distances[j] = val;
+                    }
+                    libxl_string_list_dispose(&vdist);
+                }
+                free(option);
+                free(value);
+                free(option_untrimmed);
+                free(value_untrimmed);
+            }
+        }
+    }
+
+    /* User has specified maxvcpus= */
+    if (b_info->max_vcpus != 0) {
+        if (b_info->max_vcpus != max_vcpus) {
+            fprintf(stderr, "xl: vnuma vcpus and maxvcpus= mismatch\n");
+            exit(EXIT_FAILURE);
+        }
+    } else {
+        int host_cpus = libxl_get_online_cpus(ctx);
+
+        if (host_cpus < 0) {
+            fprintf(stderr, "Failed to get online cpus\n");
+            exit(EXIT_FAILURE);
+        }
+
+        if (host_cpus < max_vcpus) {
+            fprintf(stderr, "xl: vnuma specifies more vcpus than pcpus, "\
+                    "use maxvcpus= to override this check.\n");
+            exit(EXIT_FAILURE);
+        }
+
+        b_info->max_vcpus = max_vcpus;
+    }
+
+    /* User has specified maxmem= */
+    if (b_info->max_memkb != LIBXL_MEMKB_DEFAULT &&
+        b_info->max_memkb != max_memkb) {
+        fprintf(stderr, "xl: maxmem and vnuma memory size mismatch\n");
+        exit(EXIT_FAILURE);
+    } else
+        b_info->max_memkb = max_memkb;
+
+    for (i = 0; i < b_info->num_vnuma_nodes; i++) {
+        libxl_vnode_info *p = &b_info->vnuma_nodes[i];
+
+        libxl_bitmap_copy_alloc(ctx, &p->vcpus, &vcpu_parsed[i]);
+        libxl_bitmap_dispose(&vcpu_parsed[i]);
+    }
+
+    free(vcpu_parsed);
+}
+
+/* Parses usbctrl data and adds info into usbctrl
+ * Returns 1 if the input token does not match one of the keys
+ * or parsed values are not correct. Successful parse returns 0 */
+int parse_usbctrl_config(libxl_device_usbctrl *usbctrl, char *token)
+{
+    char *oparg;
+
+    if (MATCH_OPTION("type", token, oparg)) {
+        if (libxl_usbctrl_type_from_string(oparg, &usbctrl->type)) {
+            fprintf(stderr, "Invalid usb controller type '%s'\n", oparg);
+            return 1;
+        }
+    } else if (MATCH_OPTION("version", token, oparg)) {
+        usbctrl->version = atoi(oparg);
+    } else if (MATCH_OPTION("ports", token, oparg)) {
+        usbctrl->ports = atoi(oparg);
+    } else {
+        fprintf(stderr, "Unknown string `%s' in usbctrl spec\n", token);
+        return 1;
+    }
+
+    return 0;
+}
+
+/* Parses usbdev data and adds info into usbdev
+ * Returns 1 if the input token does not match one of the keys
+ * or parsed values are not correct. Successful parse returns 0 */
+int parse_usbdev_config(libxl_device_usbdev *usbdev, char *token)
+{
+    char *oparg;
+
+    if (MATCH_OPTION("type", token, oparg)) {
+        if (libxl_usbdev_type_from_string(oparg, &usbdev->type)) {
+            fprintf(stderr, "Invalid usb device type: %s\n", optarg);
+            return 1;
+        }
+    } else if (MATCH_OPTION("hostbus", token, oparg)) {
+        usbdev->u.hostdev.hostbus = strtoul(oparg, NULL, 0);
+    } else if (MATCH_OPTION("hostaddr", token, oparg)) {
+        usbdev->u.hostdev.hostaddr = strtoul(oparg, NULL, 0);
+    } else if (MATCH_OPTION("controller", token, oparg)) {
+        usbdev->ctrl = atoi(oparg);
+    } else if (MATCH_OPTION("port", token, oparg)) {
+        usbdev->port = atoi(oparg);
+    } else {
+        fprintf(stderr, "Unknown string `%s' in usbdev spec\n", token);
+        return 1;
+    }
+
+    return 0;
+}
+
+void parse_config_data(const char *config_source,
+                       const char *config_data,
+                       int config_len,
+                       libxl_domain_config *d_config)
+{
+    const char *buf;
+    long l, vcpus = 0;
+    XLU_Config *config;
+    XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms,
+                   *usbctrls, *usbdevs;
+    XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs;
+    int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian;
+    int pci_power_mgmt = 0;
+    int pci_msitranslate = 0;
+    int pci_permissive = 0;
+    int pci_seize = 0;
+    int i, e;
+    char *kernel_basename;
+
+    libxl_domain_create_info *c_info = &d_config->c_info;
+    libxl_domain_build_info *b_info = &d_config->b_info;
+
+    config= xlu_cfg_init(stderr, config_source);
+    if (!config) {
+        fprintf(stderr, "Failed to allocate for configuration\n");
+        exit(1);
+    }
+
+    e= xlu_cfg_readdata(config, config_data, config_len);
+    if (e) {
+        fprintf(stderr, "Failed to parse config: %s\n", strerror(e));
+        exit(1);
+    }
+
+    if (!xlu_cfg_get_string (config, "init_seclabel", &buf, 0))
+        xlu_cfg_replace_string(config, "init_seclabel",
+                               &c_info->ssid_label, 0);
+
+    if (!xlu_cfg_get_string (config, "seclabel", &buf, 0)) {
+        if (c_info->ssid_label)
+            xlu_cfg_replace_string(config, "seclabel",
+                                   &b_info->exec_ssid_label, 0);
+        else
+            xlu_cfg_replace_string(config, "seclabel",
+                                   &c_info->ssid_label, 0);
+    }
+
+    libxl_defbool_set(&c_info->run_hotplug_scripts, run_hotplug_scripts);
+    c_info->type = LIBXL_DOMAIN_TYPE_PV;
+    if (!xlu_cfg_get_string (config, "builder", &buf, 0) &&
+        !strncmp(buf, "hvm", strlen(buf)))
+        c_info->type = LIBXL_DOMAIN_TYPE_HVM;
+
+    xlu_cfg_get_defbool(config, "pvh", &c_info->pvh, 0);
+    xlu_cfg_get_defbool(config, "hap", &c_info->hap, 0);
+
+    if (xlu_cfg_replace_string (config, "name", &c_info->name, 0)) {
+        fprintf(stderr, "Domain name must be specified.\n");
+        exit(1);
+    }
+
+    if (!xlu_cfg_get_string (config, "uuid", &buf, 0) ) {
+        if ( libxl_uuid_from_string(&c_info->uuid, buf) ) {
+            fprintf(stderr, "Failed to parse UUID: %s\n", buf);
+            exit(1);
+        }
+    }else{
+        libxl_uuid_generate(&c_info->uuid);
+    }
+
+    xlu_cfg_get_defbool(config, "oos", &c_info->oos, 0);
+
+    if (!xlu_cfg_get_string (config, "pool", &buf, 0))
+        xlu_cfg_replace_string(config, "pool", &c_info->pool_name, 0);
+
+    libxl_domain_build_info_init_type(b_info, c_info->type);
+    if (blkdev_start)
+        b_info->blkdev_start = strdup(blkdev_start);
+
+    /* the following is the actual config parsing with overriding
+     * values in the structures */
+    if (!xlu_cfg_get_long (config, "cpu_weight", &l, 0))
+        b_info->sched_params.weight = l;
+    if (!xlu_cfg_get_long (config, "cap", &l, 0))
+        b_info->sched_params.cap = l;
+    if (!xlu_cfg_get_long (config, "period", &l, 0))
+        b_info->sched_params.period = l;
+    if (!xlu_cfg_get_long (config, "slice", &l, 0))
+        b_info->sched_params.slice = l;
+    if (!xlu_cfg_get_long (config, "latency", &l, 0))
+        b_info->sched_params.latency = l;
+    if (!xlu_cfg_get_long (config, "extratime", &l, 0))
+        b_info->sched_params.extratime = l;
+
+    if (!xlu_cfg_get_long (config, "memory", &l, 0))
+        b_info->target_memkb = l * 1024;
+
+    if (!xlu_cfg_get_long (config, "maxmem", &l, 0))
+        b_info->max_memkb = l * 1024;
+
+    if (!xlu_cfg_get_long (config, "vcpus", &l, 0)) {
+        vcpus = l;
+        if (libxl_cpu_bitmap_alloc(ctx, &b_info->avail_vcpus, l)) {
+            fprintf(stderr, "Unable to allocate cpumap\n");
+            exit(1);
+        }
+        libxl_bitmap_set_none(&b_info->avail_vcpus);
+        while (l-- > 0)
+            libxl_bitmap_set((&b_info->avail_vcpus), l);
+    }
+
+    if (!xlu_cfg_get_long (config, "maxvcpus", &l, 0))
+        b_info->max_vcpus = l;
+
+    parse_vnuma_config(config, b_info);
+
+    /* Set max_memkb to target_memkb and max_vcpus to avail_vcpus if
+     * they are not set by user specified config option or vnuma.
+     */
+    if (b_info->max_memkb == LIBXL_MEMKB_DEFAULT)
+        b_info->max_memkb = b_info->target_memkb;
+    if (b_info->max_vcpus == 0)
+        b_info->max_vcpus = vcpus;
+
+    if (b_info->max_vcpus < vcpus) {
+        fprintf(stderr, "xl: maxvcpus < vcpus\n");
+        exit(1);
+    }
+
+    buf = NULL;
+    if (!xlu_cfg_get_list (config, "cpus", &cpus, &num_cpus, 1) ||
+        !xlu_cfg_get_string (config, "cpus", &buf, 0))
+        parse_vcpu_affinity(b_info, cpus, buf, num_cpus, /* is_hard */ true);
+
+    buf = NULL;
+    if (!xlu_cfg_get_list (config, "cpus_soft", &cpus, &num_cpus, 1) ||
+        !xlu_cfg_get_string (config, "cpus_soft", &buf, 0))
+        parse_vcpu_affinity(b_info, cpus, buf, num_cpus, false);
+
+    libxl_defbool_set(&b_info->claim_mode, claim_mode);
+
+    if (xlu_cfg_get_string (config, "on_poweroff", &buf, 0))
+        buf = "destroy";
+    if (!parse_action_on_shutdown(buf, &d_config->on_poweroff)) {
+        fprintf(stderr, "Unknown on_poweroff action \"%s\" specified\n", buf);
+        exit(1);
+    }
+
+    if (xlu_cfg_get_string (config, "on_reboot", &buf, 0))
+        buf = "restart";
+    if (!parse_action_on_shutdown(buf, &d_config->on_reboot)) {
+        fprintf(stderr, "Unknown on_reboot action \"%s\" specified\n", buf);
+        exit(1);
+    }
+
+    if (xlu_cfg_get_string (config, "on_watchdog", &buf, 0))
+        buf = "destroy";
+    if (!parse_action_on_shutdown(buf, &d_config->on_watchdog)) {
+        fprintf(stderr, "Unknown on_watchdog action \"%s\" specified\n", buf);
+        exit(1);
+    }
+
+
+    if (xlu_cfg_get_string (config, "on_crash", &buf, 0))
+        buf = "destroy";
+    if (!parse_action_on_shutdown(buf, &d_config->on_crash)) {
+        fprintf(stderr, "Unknown on_crash action \"%s\" specified\n", buf);
+        exit(1);
+    }
+
+    if (xlu_cfg_get_string (config, "on_soft_reset", &buf, 0))
+        buf = "soft-reset";
+    if (!parse_action_on_shutdown(buf, &d_config->on_soft_reset)) {
+        fprintf(stderr, "Unknown on_soft_reset action \"%s\" specified\n", buf);
+        exit(1);
+    }
+
+    /* libxl_get_required_shadow_memory() must be called after final values
+     * (default or specified) for vcpus and memory are set, because the
+     * calculation depends on those values. */
+    b_info->shadow_memkb = !xlu_cfg_get_long(config, "shadow_memory", &l, 0)
+        ? l * 1024
+        : libxl_get_required_shadow_memory(b_info->max_memkb,
+                                           b_info->max_vcpus);
+
+    xlu_cfg_get_defbool(config, "nomigrate", &b_info->disable_migrate, 0);
+
+    if (!xlu_cfg_get_long(config, "tsc_mode", &l, 1)) {
+        const char *s = libxl_tsc_mode_to_string(l);
+        fprintf(stderr, "WARNING: specifying \"tsc_mode\" as an integer is deprecated. "
+                "Please use the named parameter variant. %s%s%s\n",
+                s ? "e.g. tsc_mode=\"" : "",
+                s ? s : "",
+                s ? "\"" : "");
+
+        if (l < LIBXL_TSC_MODE_DEFAULT ||
+            l > LIBXL_TSC_MODE_NATIVE_PARAVIRT) {
+            fprintf(stderr, "ERROR: invalid value %ld for \"tsc_mode\"\n", l);
+            exit (1);
+        }
+        b_info->tsc_mode = l;
+    } else if (!xlu_cfg_get_string(config, "tsc_mode", &buf, 0)) {
+        fprintf(stderr, "got a tsc mode string: \"%s\"\n", buf);
+        if (libxl_tsc_mode_from_string(buf, &b_info->tsc_mode)) {
+            fprintf(stderr, "ERROR: invalid value \"%s\" for \"tsc_mode\"\n",
+                    buf);
+            exit (1);
+        }
+    }
+
+    if (!xlu_cfg_get_long(config, "rtc_timeoffset", &l, 0))
+        b_info->rtc_timeoffset = l;
+
+    if (!xlu_cfg_get_long(config, "vncviewer", &l, 0))
+        fprintf(stderr, "WARNING: ignoring \"vncviewer\" option. "
+                "Use \"-V\" option of \"xl create\" to automatically spawn vncviewer.\n");
+
+    xlu_cfg_get_defbool(config, "localtime", &b_info->localtime, 0);
+
+    if (!xlu_cfg_get_long (config, "videoram", &l, 0))
+        b_info->video_memkb = l * 1024;
+
+    if (!xlu_cfg_get_long(config, "max_event_channels", &l, 0))
+        b_info->event_channels = l;
+
+    xlu_cfg_replace_string (config, "kernel", &b_info->kernel, 0);
+    xlu_cfg_replace_string (config, "ramdisk", &b_info->ramdisk, 0);
+    xlu_cfg_replace_string (config, "device_tree", &b_info->device_tree, 0);
+    b_info->cmdline = parse_cmdline(config);
+
+    xlu_cfg_get_defbool(config, "driver_domain", &c_info->driver_domain, 0);
+    xlu_cfg_get_defbool(config, "acpi", &b_info->acpi, 0);
+
+    switch(b_info->type) {
+    case LIBXL_DOMAIN_TYPE_HVM:
+        kernel_basename = libxl_basename(b_info->kernel);
+        if (!strcmp(kernel_basename, "hvmloader")) {
+            fprintf(stderr, "WARNING: you seem to be using \"kernel\" "
+                    "directive to override HVM guest firmware. Ignore "
+                    "that. Use \"firmware_override\" instead if you "
+                    "really want a non-default firmware\n");
+            b_info->kernel = NULL;
+        }
+        free(kernel_basename);
+
+        xlu_cfg_replace_string (config, "firmware_override",
+                                &b_info->u.hvm.firmware, 0);
+        xlu_cfg_replace_string (config, "bios_path_override",
+                                &b_info->u.hvm.system_firmware, 0);
+        if (!xlu_cfg_get_string(config, "bios", &buf, 0)) {
+            if (libxl_bios_type_from_string(buf, &b_info->u.hvm.bios)) {
+                fprintf(stderr, "ERROR: invalid value \"%s\" for \"bios\"\n",
+                    buf);
+                exit (1);
+            }
+        } else if (b_info->u.hvm.system_firmware)
+            fprintf(stderr, "WARNING: "
+                    "bios_path_override given without specific bios name\n");
+
+        xlu_cfg_get_defbool(config, "pae", &b_info->u.hvm.pae, 0);
+        xlu_cfg_get_defbool(config, "apic", &b_info->u.hvm.apic, 0);
+        xlu_cfg_get_defbool(config, "acpi_s3", &b_info->u.hvm.acpi_s3, 0);
+        xlu_cfg_get_defbool(config, "acpi_s4", &b_info->u.hvm.acpi_s4, 0);
+        xlu_cfg_get_defbool(config, "nx", &b_info->u.hvm.nx, 0);
+        xlu_cfg_get_defbool(config, "hpet", &b_info->u.hvm.hpet, 0);
+        xlu_cfg_get_defbool(config, "vpt_align", &b_info->u.hvm.vpt_align, 0);
+
+        switch (xlu_cfg_get_list(config, "viridian",
+                                 &viridian, &num_viridian, 1))
+        {
+        case 0: /* Success */
+            if (num_viridian) {
+                libxl_bitmap_alloc(ctx, &b_info->u.hvm.viridian_enable,
+                                   LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
+                libxl_bitmap_alloc(ctx, &b_info->u.hvm.viridian_disable,
+                                   LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
+            }
+            for (i = 0; i < num_viridian; i++) {
+                libxl_viridian_enlightenment v;
+
+                buf = xlu_cfg_get_listitem(viridian, i);
+                if (strcmp(buf, "all") == 0)
+                    libxl_bitmap_set_any(&b_info->u.hvm.viridian_enable);
+                else if (strcmp(buf, "defaults") == 0)
+                    libxl_defbool_set(&b_info->u.hvm.viridian, true);
+                else {
+                    libxl_bitmap *s = &b_info->u.hvm.viridian_enable;
+                    libxl_bitmap *r = &b_info->u.hvm.viridian_disable;
+
+                    if (*buf == '!') {
+                        s = &b_info->u.hvm.viridian_disable;
+                        r = &b_info->u.hvm.viridian_enable;
+                        buf++;
+                    }
+
+                    e = libxl_viridian_enlightenment_from_string(buf, &v);
+                    if (e) {
+                        fprintf(stderr,
+                                "xl: unknown viridian enlightenment '%s'\n",
+                                buf);
+                        exit(-ERROR_FAIL);
+                    }
+
+                    libxl_bitmap_set(s, v);
+                    libxl_bitmap_reset(r, v);
+                }
+            }
+            break;
+        case ESRCH: break; /* Option not present */
+        case EINVAL:
+            xlu_cfg_get_defbool(config, "viridian", &b_info->u.hvm.viridian, 1);
+            break;
+        default:
+            fprintf(stderr,"xl: Unable to parse viridian enlightenments.\n");
+            exit(-ERROR_FAIL);
+        }
+
+        if (!xlu_cfg_get_long(config, "mmio_hole", &l, 0)) {
+            uint64_t mmio_hole_size;
+
+            b_info->u.hvm.mmio_hole_memkb = l * 1024;
+            mmio_hole_size = b_info->u.hvm.mmio_hole_memkb * 1024;
+            if (mmio_hole_size < HVM_BELOW_4G_MMIO_LENGTH ||
+                mmio_hole_size > HVM_BELOW_4G_MMIO_START) {
+                fprintf(stderr,
+                        "ERROR: invalid value %ld for \"mmio_hole\"\n", l);
+                exit (1);
+            }
+        }
+        if (!xlu_cfg_get_long(config, "timer_mode", &l, 1)) {
+            const char *s = libxl_timer_mode_to_string(l);
+            fprintf(stderr, "WARNING: specifying \"timer_mode\" as an integer is deprecated. "
+                    "Please use the named parameter variant. %s%s%s\n",
+                    s ? "e.g. timer_mode=\"" : "",
+                    s ? s : "",
+                    s ? "\"" : "");
+
+            if (l < LIBXL_TIMER_MODE_DELAY_FOR_MISSED_TICKS ||
+                l > LIBXL_TIMER_MODE_ONE_MISSED_TICK_PENDING) {
+                fprintf(stderr, "ERROR: invalid value %ld for \"timer_mode\"\n", l);
+                exit (1);
+            }
+            b_info->u.hvm.timer_mode = l;
+        } else if (!xlu_cfg_get_string(config, "timer_mode", &buf, 0)) {
+            if (libxl_timer_mode_from_string(buf, &b_info->u.hvm.timer_mode)) {
+                fprintf(stderr, "ERROR: invalid value \"%s\" for \"timer_mode\"\n",
+                        buf);
+                exit (1);
+            }
+        }
+
+        xlu_cfg_get_defbool(config, "nestedhvm", &b_info->u.hvm.nested_hvm, 0);
+
+        xlu_cfg_get_defbool(config, "altp2mhvm", &b_info->u.hvm.altp2m, 0);
+
+        xlu_cfg_replace_string(config, "smbios_firmware",
+                               &b_info->u.hvm.smbios_firmware, 0);
+        xlu_cfg_replace_string(config, "acpi_firmware",
+                               &b_info->u.hvm.acpi_firmware, 0);
+
+        if (!xlu_cfg_get_string(config, "ms_vm_genid", &buf, 0)) {
+            if (!strcmp(buf, "generate")) {
+                e = libxl_ms_vm_genid_generate(ctx, &b_info->u.hvm.ms_vm_genid);
+                if (e) {
+                    fprintf(stderr, "ERROR: failed to generate a VM Generation ID\n");
+                    exit(1);
+                }
+            } else if (!strcmp(buf, "none")) {
+                ;
+            } else {
+                    fprintf(stderr, "ERROR: \"ms_vm_genid\" option must be \"generate\" or \"none\"\n");
+                    exit(1);
+            }
+        }
+
+        if (!xlu_cfg_get_long (config, "rdm_mem_boundary", &l, 0))
+            b_info->u.hvm.rdm_mem_boundary_memkb = l * 1024;
+        break;
+    case LIBXL_DOMAIN_TYPE_PV:
+    {
+        xlu_cfg_replace_string (config, "bootloader", &b_info->u.pv.bootloader, 0);
+        switch (xlu_cfg_get_list_as_string_list(config, "bootloader_args",
+                                      &b_info->u.pv.bootloader_args, 1))
+        {
+
+        case 0: break; /* Success */
+        case ESRCH: break; /* Option not present */
+        case EINVAL:
+            if (!xlu_cfg_get_string(config, "bootloader_args", &buf, 0)) {
+
+                fprintf(stderr, "WARNING: Specifying \"bootloader_args\""
+                        " as a string is deprecated. "
+                        "Please use a list of arguments.\n");
+                split_string_into_string_list(buf, " \t\n",
+                                              &b_info->u.pv.bootloader_args);
+            }
+            break;
+        default:
+            fprintf(stderr,"xl: Unable to parse bootloader_args.\n");
+            exit(-ERROR_FAIL);
+        }
+
+        if (!b_info->u.pv.bootloader && !b_info->kernel) {
+            fprintf(stderr, "Neither kernel nor bootloader specified\n");
+            exit(1);
+        }
+
+        break;
+    }
+    default:
+        abort();
+    }
+
+    if (!xlu_cfg_get_list(config, "ioports", &ioports, &num_ioports, 0)) {
+        b_info->num_ioports = num_ioports;
+        b_info->ioports = calloc(num_ioports, sizeof(*b_info->ioports));
+        if (b_info->ioports == NULL) {
+            fprintf(stderr, "unable to allocate memory for ioports\n");
+            exit(-1);
+        }
+
+        for (i = 0; i < num_ioports; i++) {
+            const char *buf2;
+            char *ep;
+            uint32_t start, end;
+            unsigned long ul;
+
+            buf = xlu_cfg_get_listitem (ioports, i);
+            if (!buf) {
+                fprintf(stderr,
+                        "xl: Unable to get element #%d in ioport list\n", i);
+                exit(1);
+            }
+            ul = strtoul(buf, &ep, 16);
+            if (ep == buf) {
+                fprintf(stderr, "xl: Invalid argument parsing ioport: %s\n",
+                        buf);
+                exit(1);
+            }
+            if (ul >= UINT32_MAX) {
+                fprintf(stderr, "xl: ioport %lx too big\n", ul);
+                exit(1);
+            }
+            start = end = ul;
+
+            if (*ep == '-') {
+                buf2 = ep + 1;
+                ul = strtoul(buf2, &ep, 16);
+                if (ep == buf2 || *ep != '\0' || start > end) {
+                    fprintf(stderr,
+                            "xl: Invalid argument parsing ioport: %s\n", buf);
+                    exit(1);
+                }
+                if (ul >= UINT32_MAX) {
+                    fprintf(stderr, "xl: ioport %lx too big\n", ul);
+                    exit(1);
+                }
+                end = ul;
+            } else if ( *ep != '\0' )
+                fprintf(stderr,
+                        "xl: Invalid argument parsing ioport: %s\n", buf);
+            b_info->ioports[i].first = start;
+            b_info->ioports[i].number = end - start + 1;
+        }
+    }
+
+    if (!xlu_cfg_get_list(config, "irqs", &irqs, &num_irqs, 0)) {
+        b_info->num_irqs = num_irqs;
+        b_info->irqs = calloc(num_irqs, sizeof(*b_info->irqs));
+        if (b_info->irqs == NULL) {
+            fprintf(stderr, "unable to allocate memory for ioports\n");
+            exit(-1);
+        }
+        for (i = 0; i < num_irqs; i++) {
+            char *ep;
+            unsigned long ul;
+            buf = xlu_cfg_get_listitem (irqs, i);
+            if (!buf) {
+                fprintf(stderr,
+                        "xl: Unable to get element %d in irq list\n", i);
+                exit(1);
+            }
+            ul = strtoul(buf, &ep, 10);
+            if (ep == buf || *ep != '\0') {
+                fprintf(stderr,
+                        "xl: Invalid argument parsing irq: %s\n", buf);
+                exit(1);
+            }
+            if (ul >= UINT32_MAX) {
+                fprintf(stderr, "xl: irq %lx too big\n", ul);
+                exit(1);
+            }
+            b_info->irqs[i] = ul;
+        }
+    }
+
+    if (!xlu_cfg_get_list(config, "iomem", &iomem, &num_iomem, 0)) {
+        int ret;
+        b_info->num_iomem = num_iomem;
+        b_info->iomem = calloc(num_iomem, sizeof(*b_info->iomem));
+        if (b_info->iomem == NULL) {
+            fprintf(stderr, "unable to allocate memory for iomem\n");
+            exit(-1);
+        }
+        for (i = 0; i < num_iomem; i++) {
+            int used;
+
+            buf = xlu_cfg_get_listitem (iomem, i);
+            if (!buf) {
+                fprintf(stderr,
+                        "xl: Unable to get element %d in iomem list\n", i);
+                exit(1);
+            }
+            libxl_iomem_range_init(&b_info->iomem[i]);
+            ret = sscanf(buf, "%" SCNx64",%" SCNx64"%n@%" SCNx64"%n",
+                         &b_info->iomem[i].start,
+                         &b_info->iomem[i].number, &used,
+                         &b_info->iomem[i].gfn, &used);
+            if (ret < 2 || buf[used] != '\0') {
+                fprintf(stderr,
+                        "xl: Invalid argument parsing iomem: %s\n", buf);
+                exit(1);
+            }
+        }
+    }
+
+
+
+    if (!xlu_cfg_get_list (config, "disk", &vbds, 0, 0)) {
+        d_config->num_disks = 0;
+        d_config->disks = NULL;
+        while ((buf = xlu_cfg_get_listitem (vbds, d_config->num_disks)) != NULL) {
+            libxl_device_disk *disk;
+            char *buf2 = strdup(buf);
+
+            disk = ARRAY_EXTEND_INIT_NODEVID(d_config->disks,
+                                             d_config->num_disks,
+                                             libxl_device_disk_init);
+            parse_disk_config(&config, buf2, disk);
+
+            free(buf2);
+        }
+    }
+
+    if (!xlu_cfg_get_list(config, "vtpm", &vtpms, 0, 0)) {
+        d_config->num_vtpms = 0;
+        d_config->vtpms = NULL;
+        while ((buf = xlu_cfg_get_listitem (vtpms, d_config->num_vtpms)) != NULL) {
+            libxl_device_vtpm *vtpm;
+            char * buf2 = strdup(buf);
+            char *p, *p2;
+            bool got_backend = false;
+
+            vtpm = ARRAY_EXTEND_INIT(d_config->vtpms,
+                                     d_config->num_vtpms,
+                                     libxl_device_vtpm_init);
+
+            p = strtok(buf2, ",");
+            if(p) {
+               do {
+                  while(*p == ' ')
+                     ++p;
+                  if ((p2 = strchr(p, '=')) == NULL)
+                     break;
+                  *p2 = '\0';
+                  if (!strcmp(p, "backend")) {
+                     vtpm->backend_domname = strdup(p2 + 1);
+                     got_backend = true;
+                  } else if(!strcmp(p, "uuid")) {
+                     if( libxl_uuid_from_string(&vtpm->uuid, p2 + 1) ) {
+                        fprintf(stderr,
+                              "Failed to parse vtpm UUID: %s\n", p2 + 1);
+                        exit(1);
+                    }
+                  } else {
+                     fprintf(stderr, "Unknown string `%s' in vtpm spec\n", p);
+                     exit(1);
+                  }
+               } while ((p = strtok(NULL, ",")) != NULL);
+            }
+            if(!got_backend) {
+               fprintf(stderr, "vtpm spec missing required backend field!\n");
+               exit(1);
+            }
+            free(buf2);
+        }
+    }
+
+    if (!xlu_cfg_get_list (config, "channel", &channels, 0, 0)) {
+        d_config->num_channels = 0;
+        d_config->channels = NULL;
+        while ((buf = xlu_cfg_get_listitem (channels,
+                d_config->num_channels)) != NULL) {
+            libxl_device_channel *chn;
+            libxl_string_list pairs;
+            char *path = NULL;
+            int len;
+
+            chn = ARRAY_EXTEND_INIT(d_config->channels, d_config->num_channels,
+                                   libxl_device_channel_init);
+
+            split_string_into_string_list(buf, ",", &pairs);
+            len = libxl_string_list_length(&pairs);
+            for (i = 0; i < len; i++) {
+                char *key, *key_untrimmed, *value, *value_untrimmed;
+                int rc;
+                rc = split_string_into_pair(pairs[i], "=",
+                                            &key_untrimmed,
+                                            &value_untrimmed);
+                if (rc != 0) {
+                    fprintf(stderr, "failed to parse channel configuration: %s",
+                            pairs[i]);
+                    exit(1);
+                }
+                trim(isspace, key_untrimmed, &key);
+                trim(isspace, value_untrimmed, &value);
+
+                if (!strcmp(key, "backend")) {
+                    replace_string(&chn->backend_domname, value);
+                } else if (!strcmp(key, "name")) {
+                    replace_string(&chn->name, value);
+                } else if (!strcmp(key, "path")) {
+                    replace_string(&path, value);
+                } else if (!strcmp(key, "connection")) {
+                    if (!strcmp(value, "pty")) {
+                        chn->connection = LIBXL_CHANNEL_CONNECTION_PTY;
+                    } else if (!strcmp(value, "socket")) {
+                        chn->connection = LIBXL_CHANNEL_CONNECTION_SOCKET;
+                    } else {
+                        fprintf(stderr, "unknown channel connection '%s'\n",
+                                value);
+                        exit(1);
+                    }
+                } else {
+                    fprintf(stderr, "unknown channel parameter '%s',"
+                                  " ignoring\n", key);
+                }
+                free(key);
+                free(key_untrimmed);
+                free(value);
+                free(value_untrimmed);
+            }
+            switch (chn->connection) {
+            case LIBXL_CHANNEL_CONNECTION_UNKNOWN:
+                fprintf(stderr, "channel has unknown 'connection'\n");
+                exit(1);
+            case LIBXL_CHANNEL_CONNECTION_SOCKET:
+                if (!path) {
+                    fprintf(stderr, "channel connection 'socket' requires path=..\n");
+                    exit(1);
+                }
+                chn->u.socket.path = xstrdup(path);
+                break;
+            case LIBXL_CHANNEL_CONNECTION_PTY:
+                /* Nothing to do since PTY has no arguments */
+                break;
+            default:
+                fprintf(stderr, "unknown channel connection: %d",
+                        chn->connection);
+                exit(1);
+            }
+            libxl_string_list_dispose(&pairs);
+            free(path);
+        }
+    }
+
+    if (!xlu_cfg_get_list (config, "vif", &nics, 0, 0)) {
+        d_config->num_nics = 0;
+        d_config->nics = NULL;
+        while ((buf = xlu_cfg_get_listitem (nics, d_config->num_nics)) != NULL) {
+            libxl_device_nic *nic;
+            char *buf2 = strdup(buf);
+            char *p;
+
+            nic = ARRAY_EXTEND_INIT(d_config->nics,
+                                    d_config->num_nics,
+                                    libxl_device_nic_init);
+            set_default_nic_values(nic);
+
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip_nic;
+            do {
+                while (*p == ' ')
+                    p++;
+                parse_nic_config(nic, &config, p);
+            } while ((p = strtok(NULL, ",")) != NULL);
+skip_nic:
+            free(buf2);
+        }
+    }
+
+    if (!xlu_cfg_get_list(config, "vif2", NULL, 0, 0)) {
+        fprintf(stderr, "WARNING: vif2: netchannel2 is deprecated and not supported by xl\n");
+    }
+
+    d_config->num_vfbs = 0;
+    d_config->num_vkbs = 0;
+    d_config->vfbs = NULL;
+    d_config->vkbs = NULL;
+
+    if (!xlu_cfg_get_list (config, "vfb", &cvfbs, 0, 0)) {
+        while ((buf = xlu_cfg_get_listitem (cvfbs, d_config->num_vfbs)) != NULL) {
+            libxl_device_vfb *vfb;
+            libxl_device_vkb *vkb;
+
+            char *buf2 = strdup(buf);
+            char *p, *p2;
+
+            vfb = ARRAY_EXTEND_INIT(d_config->vfbs, d_config->num_vfbs,
+                                    libxl_device_vfb_init);
+
+            vkb = ARRAY_EXTEND_INIT(d_config->vkbs, d_config->num_vkbs,
+                                    libxl_device_vkb_init);
+
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip_vfb;
+            do {
+                while (*p == ' ')
+                    p++;
+                if ((p2 = strchr(p, '=')) == NULL)
+                    break;
+                *p2 = '\0';
+                if (!strcmp(p, "vnc")) {
+                    libxl_defbool_set(&vfb->vnc.enable, atoi(p2 + 1));
+                } else if (!strcmp(p, "vnclisten")) {
+                    free(vfb->vnc.listen);
+                    vfb->vnc.listen = strdup(p2 + 1);
+                } else if (!strcmp(p, "vncpasswd")) {
+                    free(vfb->vnc.passwd);
+                    vfb->vnc.passwd = strdup(p2 + 1);
+                } else if (!strcmp(p, "vncdisplay")) {
+                    vfb->vnc.display = atoi(p2 + 1);
+                } else if (!strcmp(p, "vncunused")) {
+                    libxl_defbool_set(&vfb->vnc.findunused, atoi(p2 + 1));
+                } else if (!strcmp(p, "keymap")) {
+                    free(vfb->keymap);
+                    vfb->keymap = strdup(p2 + 1);
+                } else if (!strcmp(p, "sdl")) {
+                    libxl_defbool_set(&vfb->sdl.enable, atoi(p2 + 1));
+                } else if (!strcmp(p, "opengl")) {
+                    libxl_defbool_set(&vfb->sdl.opengl, atoi(p2 + 1));
+                } else if (!strcmp(p, "display")) {
+                    free(vfb->sdl.display);
+                    vfb->sdl.display = strdup(p2 + 1);
+                } else if (!strcmp(p, "xauthority")) {
+                    free(vfb->sdl.xauthority);
+                    vfb->sdl.xauthority = strdup(p2 + 1);
+                }
+            } while ((p = strtok(NULL, ",")) != NULL);
+
+skip_vfb:
+            free(buf2);
+        }
+    }
+
+    if (!xlu_cfg_get_long (config, "pci_msitranslate", &l, 0))
+        pci_msitranslate = l;
+
+    if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l, 0))
+        pci_power_mgmt = l;
+
+    if (!xlu_cfg_get_long (config, "pci_permissive", &l, 0))
+        pci_permissive = l;
+
+    if (!xlu_cfg_get_long (config, "pci_seize", &l, 0))
+        pci_seize = l;
+
+    /* To be reworked (automatically enabled) once the auto ballooning
+     * after guest starts is done (with PCI devices passed in). */
+    if (c_info->type == LIBXL_DOMAIN_TYPE_PV) {
+        xlu_cfg_get_defbool(config, "e820_host", &b_info->u.pv.e820_host, 0);
+    }
+
+    if (!xlu_cfg_get_string(config, "rdm", &buf, 0)) {
+        libxl_rdm_reserve rdm;
+        if (!xlu_rdm_parse(config, &rdm, buf)) {
+            b_info->u.hvm.rdm.strategy = rdm.strategy;
+            b_info->u.hvm.rdm.policy = rdm.policy;
+        }
+    }
+
+    if (!xlu_cfg_get_list (config, "pci", &pcis, 0, 0)) {
+        d_config->num_pcidevs = 0;
+        d_config->pcidevs = NULL;
+        for(i = 0; (buf = xlu_cfg_get_listitem (pcis, i)) != NULL; i++) {
+            libxl_device_pci *pcidev;
+
+            pcidev = ARRAY_EXTEND_INIT_NODEVID(d_config->pcidevs,
+                                               d_config->num_pcidevs,
+                                               libxl_device_pci_init);
+            pcidev->msitranslate = pci_msitranslate;
+            pcidev->power_mgmt = pci_power_mgmt;
+            pcidev->permissive = pci_permissive;
+            pcidev->seize = pci_seize;
+            /*
+             * Like other pci option, the per-device policy always follows
+             * the global policy by default.
+             */
+            pcidev->rdm_policy = b_info->u.hvm.rdm.policy;
+            e = xlu_pci_parse_bdf(config, pcidev, buf);
+            if (e) {
+                fprintf(stderr,
+                        "unable to parse PCI BDF `%s' for passthrough\n",
+                        buf);
+                exit(-e);
+            }
+        }
+        if (d_config->num_pcidevs && c_info->type == LIBXL_DOMAIN_TYPE_PV)
+            libxl_defbool_set(&b_info->u.pv.e820_host, true);
+    }
+
+    if (!xlu_cfg_get_list (config, "dtdev", &dtdevs, 0, 0)) {
+        d_config->num_dtdevs = 0;
+        d_config->dtdevs = NULL;
+        for (i = 0; (buf = xlu_cfg_get_listitem(dtdevs, i)) != NULL; i++) {
+            libxl_device_dtdev *dtdev;
+
+            dtdev = ARRAY_EXTEND_INIT_NODEVID(d_config->dtdevs,
+                                              d_config->num_dtdevs,
+                                              libxl_device_dtdev_init);
+
+            dtdev->path = strdup(buf);
+            if (dtdev->path == NULL) {
+                fprintf(stderr, "unable to duplicate string for dtdevs\n");
+                exit(-1);
+            }
+        }
+    }
+
+    if (!xlu_cfg_get_list(config, "usbctrl", &usbctrls, 0, 0)) {
+        d_config->num_usbctrls = 0;
+        d_config->usbctrls = NULL;
+        while ((buf = xlu_cfg_get_listitem(usbctrls, d_config->num_usbctrls))
+               != NULL) {
+            libxl_device_usbctrl *usbctrl;
+            char *buf2 = strdup(buf);
+            char *p;
+
+            usbctrl = ARRAY_EXTEND_INIT(d_config->usbctrls,
+                                        d_config->num_usbctrls,
+                                        libxl_device_usbctrl_init);
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip_usbctrl;
+            do {
+                while (*p == ' ')
+                    p++;
+                if (parse_usbctrl_config(usbctrl, p))
+                    exit(1);
+            } while ((p = strtok(NULL, ",")) != NULL);
+skip_usbctrl:
+            free(buf2);
+        }
+    }
+
+    if (!xlu_cfg_get_list(config, "usbdev", &usbdevs, 0, 0)) {
+        d_config->num_usbdevs = 0;
+        d_config->usbdevs = NULL;
+        while ((buf = xlu_cfg_get_listitem(usbdevs, d_config->num_usbdevs))
+               != NULL) {
+            libxl_device_usbdev *usbdev;
+            char *buf2 = strdup(buf);
+            char *p;
+
+            usbdev = ARRAY_EXTEND_INIT_NODEVID(d_config->usbdevs,
+                                               d_config->num_usbdevs,
+                                               libxl_device_usbdev_init);
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip_usbdev;
+            do {
+                while (*p == ' ')
+                    p++;
+                if (parse_usbdev_config(usbdev, p))
+                    exit(1);
+            } while ((p = strtok(NULL, ",")) != NULL);
+skip_usbdev:
+            free(buf2);
+        }
+    }
+
+    switch (xlu_cfg_get_list(config, "cpuid", &cpuids, 0, 1)) {
+    case 0:
+        {
+            const char *errstr;
+
+            for (i = 0; (buf = xlu_cfg_get_listitem(cpuids, i)) != NULL; i++) {
+                e = libxl_cpuid_parse_config_xend(&b_info->cpuid, buf);
+                switch (e) {
+                case 0: continue;
+                case 1:
+                    errstr = "illegal leaf number";
+                    break;
+                case 2:
+                    errstr = "illegal subleaf number";
+                    break;
+                case 3:
+                    errstr = "missing colon";
+                    break;
+                case 4:
+                    errstr = "invalid register name (must be e[abcd]x)";
+                    break;
+                case 5:
+                    errstr = "policy string must be exactly 32 characters long";
+                    break;
+                default:
+                    errstr = "unknown error";
+                    break;
+                }
+                fprintf(stderr, "while parsing CPUID line: \"%s\":\n", buf);
+                fprintf(stderr, "  error #%i: %s\n", e, errstr);
+            }
+        }
+        break;
+    case EINVAL:    /* config option is not a list, parse as a string */
+        if (!xlu_cfg_get_string(config, "cpuid", &buf, 0)) {
+            char *buf2, *p, *strtok_ptr = NULL;
+            const char *errstr;
+
+            buf2 = strdup(buf);
+            p = strtok_r(buf2, ",", &strtok_ptr);
+            if (p == NULL) {
+                free(buf2);
+                break;
+            }
+            if (strcmp(p, "host")) {
+                fprintf(stderr, "while parsing CPUID string: \"%s\":\n", buf);
+                fprintf(stderr, "  error: first word must be \"host\"\n");
+                free(buf2);
+                break;
+            }
+            for (p = strtok_r(NULL, ",", &strtok_ptr); p != NULL;
+                 p = strtok_r(NULL, ",", &strtok_ptr)) {
+                e = libxl_cpuid_parse_config(&b_info->cpuid, p);
+                switch (e) {
+                case 0: continue;
+                case 1:
+                    errstr = "missing \"=\" in key=value";
+                    break;
+                case 2:
+                    errstr = "unknown CPUID flag name";
+                    break;
+                case 3:
+                    errstr = "illegal CPUID value (must be: [0|1|x|k|s])";
+                    break;
+                default:
+                    errstr = "unknown error";
+                    break;
+                }
+                fprintf(stderr, "while parsing CPUID flag: \"%s\":\n", p);
+                fprintf(stderr, "  error #%i: %s\n", e, errstr);
+            }
+            free(buf2);
+        }
+        break;
+    default:
+        break;
+    }
+
+    /* parse device model arguments, this works for pv, hvm and stubdom */
+    if (!xlu_cfg_get_string (config, "device_model", &buf, 0)) {
+        fprintf(stderr,
+                "WARNING: ignoring device_model directive.\n"
+                "WARNING: Use \"device_model_override\" instead if you"
+                " really want a non-default device_model\n");
+        if (strstr(buf, "stubdom-dm")) {
+            if (c_info->type == LIBXL_DOMAIN_TYPE_HVM)
+                fprintf(stderr, "WARNING: Or use"
+                        " \"device_model_stubdomain_override\" if you "
+                        " want to enable stubdomains\n");
+            else
+                fprintf(stderr, "WARNING: ignoring"
+                        " \"device_model_stubdomain_override\" directive"
+                        " for pv guest\n");
+        }
+    }
+
+
+    xlu_cfg_replace_string (config, "device_model_override",
+                            &b_info->device_model, 0);
+    if (!xlu_cfg_get_string (config, "device_model_version", &buf, 0)) {
+        if (!strcmp(buf, "qemu-xen-traditional")) {
+            b_info->device_model_version
+                = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL;
+        } else if (!strcmp(buf, "qemu-xen")) {
+            b_info->device_model_version
+                = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN;
+        } else if (!strcmp(buf, "none")) {
+            b_info->device_model_version = LIBXL_DEVICE_MODEL_VERSION_NONE;
+        } else {
+            fprintf(stderr,
+                    "Unknown device_model_version \"%s\" specified\n", buf);
+            exit(1);
+        }
+    } else if (b_info->device_model)
+        fprintf(stderr, "WARNING: device model override given without specific DM version\n");
+    xlu_cfg_get_defbool (config, "device_model_stubdomain_override",
+                         &b_info->device_model_stubdomain, 0);
+
+    if (!xlu_cfg_get_string (config, "device_model_stubdomain_seclabel",
+                             &buf, 0))
+        xlu_cfg_replace_string(config, "device_model_stubdomain_seclabel",
+                               &b_info->device_model_ssid_label, 0);
+
+    xlu_cfg_replace_string(config, "device_model_user",
+                           &b_info->device_model_user, 0);
+
+#define parse_extra_args(type)                                            \
+    e = xlu_cfg_get_list_as_string_list(config, "device_model_args"#type, \
+                                    &b_info->extra##type, 0);            \
+    if (e && e != ESRCH) {                                                \
+        fprintf(stderr,"xl: Unable to parse device_model_args"#type".\n");\
+        exit(-ERROR_FAIL);                                                \
+    }
+
+    /* parse extra args for qemu, common to both pv, hvm */
+    parse_extra_args();
+
+    /* parse extra args dedicated to pv */
+    parse_extra_args(_pv);
+
+    /* parse extra args dedicated to hvm */
+    parse_extra_args(_hvm);
+
+#undef parse_extra_args
+
+    /* If we've already got vfb=[] for PV guest then ignore top level
+     * VNC config. */
+    if (c_info->type == LIBXL_DOMAIN_TYPE_PV && !d_config->num_vfbs) {
+        long vnc_enabled = 0;
+
+        if (!xlu_cfg_get_long (config, "vnc", &l, 0))
+            vnc_enabled = l;
+
+        if (vnc_enabled) {
+            libxl_device_vfb *vfb;
+            libxl_device_vkb *vkb;
+
+            vfb = ARRAY_EXTEND_INIT(d_config->vfbs, d_config->num_vfbs,
+                                    libxl_device_vfb_init);
+
+            vkb = ARRAY_EXTEND_INIT(d_config->vkbs, d_config->num_vkbs,
+                                    libxl_device_vkb_init);
+
+            parse_top_level_vnc_options(config, &vfb->vnc);
+            parse_top_level_sdl_options(config, &vfb->sdl);
+            xlu_cfg_replace_string (config, "keymap", &vfb->keymap, 0);
+        }
+    } else {
+        parse_top_level_vnc_options(config, &b_info->u.hvm.vnc);
+        parse_top_level_sdl_options(config, &b_info->u.hvm.sdl);
+    }
+
+    if (c_info->type == LIBXL_DOMAIN_TYPE_HVM) {
+        if (!xlu_cfg_get_string (config, "vga", &buf, 0)) {
+            if (!strcmp(buf, "stdvga")) {
+                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_STD;
+            } else if (!strcmp(buf, "cirrus")) {
+                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
+            } else if (!strcmp(buf, "none")) {
+                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_NONE;
+            } else if (!strcmp(buf, "qxl")) {
+                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_QXL;
+            } else {
+                fprintf(stderr, "Unknown vga \"%s\" specified\n", buf);
+                exit(1);
+            }
+        } else if (!xlu_cfg_get_long(config, "stdvga", &l, 0))
+            b_info->u.hvm.vga.kind = l ? LIBXL_VGA_INTERFACE_TYPE_STD :
+                                         LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
+
+        if (!xlu_cfg_get_string(config, "hdtype", &buf, 0) &&
+            libxl_hdtype_from_string(buf, &b_info->u.hvm.hdtype)) {
+                fprintf(stderr, "ERROR: invalid value \"%s\" for \"hdtype\"\n",
+                    buf);
+                exit (1);
+        }
+
+        xlu_cfg_replace_string (config, "keymap", &b_info->u.hvm.keymap, 0);
+        xlu_cfg_get_defbool (config, "spice", &b_info->u.hvm.spice.enable, 0);
+        if (!xlu_cfg_get_long (config, "spiceport", &l, 0))
+            b_info->u.hvm.spice.port = l;
+        if (!xlu_cfg_get_long (config, "spicetls_port", &l, 0))
+            b_info->u.hvm.spice.tls_port = l;
+        xlu_cfg_replace_string (config, "spicehost",
+                                &b_info->u.hvm.spice.host, 0);
+        xlu_cfg_get_defbool(config, "spicedisable_ticketing",
+                            &b_info->u.hvm.spice.disable_ticketing, 0);
+        xlu_cfg_replace_string (config, "spicepasswd",
+                                &b_info->u.hvm.spice.passwd, 0);
+        xlu_cfg_get_defbool(config, "spiceagent_mouse",
+                            &b_info->u.hvm.spice.agent_mouse, 0);
+        xlu_cfg_get_defbool(config, "spicevdagent",
+                            &b_info->u.hvm.spice.vdagent, 0);
+        xlu_cfg_get_defbool(config, "spice_clipboard_sharing",
+                            &b_info->u.hvm.spice.clipboard_sharing, 0);
+        if (!xlu_cfg_get_long (config, "spiceusbredirection", &l, 0))
+            b_info->u.hvm.spice.usbredirection = l;
+        xlu_cfg_replace_string (config, "spice_image_compression",
+                                &b_info->u.hvm.spice.image_compression, 0);
+        xlu_cfg_replace_string (config, "spice_streaming_video",
+                                &b_info->u.hvm.spice.streaming_video, 0);
+        xlu_cfg_get_defbool(config, "nographic", &b_info->u.hvm.nographic, 0);
+        if (!xlu_cfg_get_long(config, "gfx_passthru", &l, 1)) {
+            libxl_defbool_set(&b_info->u.hvm.gfx_passthru, l);
+        } else if (!xlu_cfg_get_string(config, "gfx_passthru", &buf, 0)) {
+            if (libxl_gfx_passthru_kind_from_string(buf,
+                                        &b_info->u.hvm.gfx_passthru_kind)) {
+                fprintf(stderr,
+                        "ERROR: invalid value \"%s\" for \"gfx_passthru\"\n",
+                        buf);
+                exit (1);
+            }
+            libxl_defbool_set(&b_info->u.hvm.gfx_passthru, true);
+        }
+        switch (xlu_cfg_get_list_as_string_list(config, "serial",
+                                                &b_info->u.hvm.serial_list,
+                                                1))
+        {
+
+        case 0: break; /* Success */
+        case ESRCH: break; /* Option not present */
+        case EINVAL:
+            /* If it's not a valid list, try reading it as an atom,
+             * falling through to an error if it fails */
+            if (!xlu_cfg_replace_string(config, "serial",
+                                        &b_info->u.hvm.serial, 0))
+                break;
+            /* FALLTHRU */
+        default:
+            fprintf(stderr,"xl: Unable to parse serial.\n");
+            exit(-ERROR_FAIL);
+        }
+        xlu_cfg_replace_string (config, "boot", &b_info->u.hvm.boot, 0);
+        xlu_cfg_get_defbool(config, "usb", &b_info->u.hvm.usb, 0);
+        if (!xlu_cfg_get_long (config, "usbversion", &l, 0))
+            b_info->u.hvm.usbversion = l;
+        switch (xlu_cfg_get_list_as_string_list(config, "usbdevice",
+                                                &b_info->u.hvm.usbdevice_list,
+                                                1))
+        {
+
+        case 0: break; /* Success */
+        case ESRCH: break; /* Option not present */
+        case EINVAL:
+            /* If it's not a valid list, try reading it as an atom,
+             * falling through to an error if it fails */
+            if (!xlu_cfg_replace_string(config, "usbdevice",
+                                        &b_info->u.hvm.usbdevice, 0))
+                break;
+            /* FALLTHRU */
+        default:
+            fprintf(stderr,"xl: Unable to parse usbdevice.\n");
+            exit(-ERROR_FAIL);
+        }
+        xlu_cfg_replace_string (config, "soundhw", &b_info->u.hvm.soundhw, 0);
+        xlu_cfg_get_defbool(config, "xen_platform_pci",
+                            &b_info->u.hvm.xen_platform_pci, 0);
+
+        if(b_info->u.hvm.vnc.listen
+           && b_info->u.hvm.vnc.display
+           && strchr(b_info->u.hvm.vnc.listen, ':') != NULL) {
+            fprintf(stderr,
+                    "ERROR: Display specified both in vnclisten"
+                    " and vncdisplay!\n");
+            exit (1);
+
+        }
+
+        if (!xlu_cfg_get_string (config, "vendor_device", &buf, 0)) {
+            libxl_vendor_device d;
+
+            e = libxl_vendor_device_from_string(buf, &d);
+            if (e) {
+                fprintf(stderr,
+                        "xl: unknown vendor_device '%s'\n",
+                        buf);
+                exit(-ERROR_FAIL);
+            }
+
+            b_info->u.hvm.vendor_device = d;
+        }
+    }
+
+    if (!xlu_cfg_get_string (config, "gic_version", &buf, 1)) {
+        e = libxl_gic_version_from_string(buf, &b_info->arch_arm.gic_version);
+        if (e) {
+            fprintf(stderr,
+                    "Unknown gic_version \"%s\" specified\n", buf);
+            exit(-ERROR_FAIL);
+        }
+     }
+
+    xlu_cfg_destroy(config);
+}
+
+/* Returns -1 on failure; the amount of memory on success. */
+int64_t parse_mem_size_kb(const char *mem)
+{
+    char *endptr;
+    int64_t kbytes;
+
+    kbytes = strtoll(mem, &endptr, 10);
+
+    if (strlen(endptr) > 1)
+        return -1;
+
+    switch (tolower((uint8_t)*endptr)) {
+    case 't':
+        kbytes <<= 10;
+        /* fallthrough */
+    case 'g':
+        kbytes <<= 10;
+        /* fallthrough */
+    case '\0':
+    case 'm':
+        kbytes <<= 10;
+        /* fallthrough */
+    case 'k':
+        break;
+    case 'b':
+        kbytes >>= 10;
+        break;
+    default:
+        return -1;
+    }
+
+    return kbytes;
+}
+
+
+void split_string_into_string_list(const char *str,
+                                   const char *delim,
+                                   libxl_string_list *psl)
+{
+    char *s, *saveptr;
+    const char *p;
+    libxl_string_list sl;
+
+    int i = 0, nr = 0;
+
+    s = strdup(str);
+    if (s == NULL) {
+        fprintf(stderr, "unable to allocate memory to split string\n");
+        exit(-1);
+    }
+
+    /* Count number of entries */
+    p = strtok_r(s, delim, &saveptr);
+    do {
+        nr++;
+    } while ((p = strtok_r(NULL, delim, &saveptr)));
+
+    free(s);
+
+    s = strdup(str);
+
+    sl = malloc((nr+1) * sizeof (char *));
+    if (sl == NULL) {
+        fprintf(stderr, "unable to allocate memory to split string\n");
+        exit(-1);
+    }
+
+    p = strtok_r(s, delim, &saveptr);
+    do {
+        assert(i < nr);
+        sl[i] = strdup(p);
+        i++;
+    } while ((p = strtok_r(NULL, delim, &saveptr)));
+    sl[i] = NULL;
+
+    *psl = sl;
+
+    free(s);
+}
+
+void trim(char_predicate_t predicate, const char *input, char **output)
+{
+    const char *first, *after;
+
+    for (first = input;
+         *first && predicate((unsigned char)first[0]);
+         first++)
+        ;
+
+    for (after = first + strlen(first);
+         after > first && predicate((unsigned char)after[-1]);
+         after--)
+        ;
+
+    size_t len_nonnull = after - first;
+    char *result = xmalloc(len_nonnull + 1);
+
+    memcpy(result, first, len_nonnull);
+    result[len_nonnull] = 0;
+
+    *output = result;
+}
+
+int split_string_into_pair(const char *str,
+                           const char *delim,
+                           char **a,
+                           char **b)
+{
+    char *s, *p, *saveptr, *aa = NULL, *bb = NULL;
+    int rc = 0;
+
+    s = xstrdup(str);
+
+    p = strtok_r(s, delim, &saveptr);
+    if (p == NULL) {
+        rc = ERROR_INVAL;
+        goto out;
+    }
+    aa = xstrdup(p);
+    p = strtok_r(NULL, delim, &saveptr);
+    if (p == NULL) {
+        rc = ERROR_INVAL;
+        goto out;
+    }
+    bb = xstrdup(p);
+
+    *a = aa;
+    aa = NULL;
+    *b = bb;
+    bb = NULL;
+out:
+    free(s);
+    free(aa);
+    free(bb);
+    return rc;
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/xl/xl_parse.h b/tools/xl/xl_parse.h
new file mode 100644
index 0000000000..db8bc3f051
--- /dev/null
+++ b/tools/xl/xl_parse.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#ifndef XL_PARSE_H
+#define XL_PARSE_H
+
+#include <libxl.h>
+
+void parse_config_data(const char *config_source,
+                       const char *config_data,
+                       int config_len,
+                       libxl_domain_config *d_config);
+int parse_range(const char *str, unsigned long *a, unsigned long *b);
+int64_t parse_mem_size_kb(const char *mem);
+void parse_disk_config(XLU_Config **config, const char *spec,
+                       libxl_device_disk *disk);
+
+void parse_disk_config_multistring(XLU_Config **config,
+                                   int nspecs, const char *const *specs,
+                                   libxl_device_disk *disk);
+int parse_usbctrl_config(libxl_device_usbctrl *usbctrl, char *token);
+int parse_usbdev_config(libxl_device_usbdev *usbdev, char *token);
+int parse_cpurange(const char *cpu, libxl_bitmap *cpumap);
+int parse_nic_config(libxl_device_nic *nic, XLU_Config **config, char *token);
+
+
+int match_option_size(const char *prefix, size_t len,
+                      char *arg, char **argopt);
+#define MATCH_OPTION(prefix, arg, oparg) \
+    match_option_size((prefix "="), sizeof((prefix)), (arg), &(oparg))
+
+
+void split_string_into_string_list(const char *str, const char *delim,
+                                   libxl_string_list *psl);
+int split_string_into_pair(const char *str, const char *delim,
+                           char **a, char **b);
+void replace_string(char **str, const char *val);
+
+/* NB: this follows the interface used by <ctype.h>. See 'man 3 ctype'
+   and look for CTYPE in libxl_internal.h */
+typedef int (*char_predicate_t)(const int c);
+void trim(char_predicate_t predicate, const char *input, char **output);
+
+const char *get_action_on_shutdown_name(libxl_action_on_shutdown a);
+
+#endif	/* XL_PARSE_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 11/29] xl: split out cpupool related code
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (9 preceding siblings ...)
  2017-02-24 16:12 ` [PATCH 10/29] xl: split out xl_parse.[ch] Wei Liu
@ 2017-02-24 16:12 ` Wei Liu
  2017-02-27 15:59   ` Ian Jackson
  2017-02-24 16:12 ` [PATCH 12/29] xl: split out flask " Wei Liu
                   ` (17 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:12 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   2 +-
 tools/xl/xl_cmdimpl.c | 592 -----------------------------------------------
 tools/xl/xl_cpupool.c | 624 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 625 insertions(+), 593 deletions(-)
 create mode 100644 tools/xl/xl_cpupool.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index d7f7f01549..0ff7ef9bfe 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -16,7 +16,7 @@ CFLAGS_XL += $(CFLAGS_libxenlight)
 CFLAGS_XL += -Wshadow
 
 XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
-XL_OBJS += xl_tmem.o xl_parse.o
+XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index 812f570d0d..82b30bb094 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -5611,598 +5611,6 @@ int main_uptime(int argc, char **argv)
     return 0;
 }
 
-
-int main_cpupoolcreate(int argc, char **argv)
-{
-    const char *filename = NULL, *config_src=NULL;
-    const char *p;
-    char *extra_config = NULL;
-    int opt;
-    static struct option opts[] = {
-        {"defconfig", 1, 0, 'f'},
-        {"dryrun", 0, 0, 'n'},
-        COMMON_LONG_OPTS
-    };
-    int ret;
-    char *config_data = 0;
-    int config_len = 0;
-    XLU_Config *config;
-    const char *buf;
-    char *name = NULL;
-    uint32_t poolid;
-    libxl_scheduler sched = 0;
-    XLU_ConfigList *cpus;
-    XLU_ConfigList *nodes;
-    int n_cpus, n_nodes, i, n;
-    libxl_bitmap freemap;
-    libxl_bitmap cpumap;
-    libxl_uuid uuid;
-    libxl_cputopology *topology;
-    int rc = EXIT_FAILURE;
-
-    SWITCH_FOREACH_OPT(opt, "nf:", opts, "cpupool-create", 0) {
-    case 'f':
-        filename = optarg;
-        break;
-    case 'n':
-        dryrun_only = 1;
-        break;
-    }
-
-    libxl_bitmap_init(&freemap);
-    libxl_bitmap_init(&cpumap);
-
-    while (optind < argc) {
-        if ((p = strchr(argv[optind], '='))) {
-            xstring_realloc_append(&extra_config, "\n");
-            xstring_realloc_append(&extra_config, argv[optind]);
-        } else if (!filename) {
-            filename = argv[optind];
-        } else {
-            help("cpupool-create");
-            goto out;
-        }
-        optind++;
-    }
-
-    if (filename)
-    {
-        if (libxl_read_file_contents(ctx, filename, (void **)&config_data,
-                                     &config_len)) {
-            fprintf(stderr, "Failed to read config file: %s: %s\n",
-                    filename, strerror(errno));
-            goto out;
-        }
-        config_src=filename;
-    }
-    else
-        config_src="command line";
-
-    if (extra_config && strlen(extra_config)) {
-        if (config_len > INT_MAX - (strlen(extra_config) + 2)) {
-            fprintf(stderr, "Failed to attach extra configuration\n");
-            goto out;
-        }
-        config_data = xrealloc(config_data,
-                               config_len + strlen(extra_config) + 2);
-        if (!config_data) {
-            fprintf(stderr, "Failed to realloc config_data\n");
-            goto out;
-        }
-        config_data[config_len] = 0;
-        strcat(config_data, extra_config);
-        strcat(config_data, "\n");
-        config_len += strlen(extra_config) + 1;
-    }
-
-    config = xlu_cfg_init(stderr, config_src);
-    if (!config) {
-        fprintf(stderr, "Failed to allocate for configuration\n");
-        goto out;
-    }
-
-    ret = xlu_cfg_readdata(config, config_data, config_len);
-    if (ret) {
-        fprintf(stderr, "Failed to parse config file: %s\n", strerror(ret));
-        goto out_cfg;
-    }
-
-    if (!xlu_cfg_get_string (config, "name", &buf, 0))
-        name = strdup(buf);
-    else if (filename)
-        name = libxl_basename(filename);
-    else {
-        fprintf(stderr, "Missing cpupool name!\n");
-        goto out_cfg;
-    }
-    if (!libxl_name_to_cpupoolid(ctx, name, &poolid)) {
-        fprintf(stderr, "Pool name \"%s\" already exists\n", name);
-        goto out_cfg;
-    }
-
-    if (!xlu_cfg_get_string (config, "sched", &buf, 0)) {
-        if ((libxl_scheduler_from_string(buf, &sched)) < 0) {
-            fprintf(stderr, "Unknown scheduler\n");
-            goto out_cfg;
-        }
-    } else {
-        rc = libxl_get_scheduler(ctx);
-        if (rc < 0) {
-            fprintf(stderr, "get_scheduler sysctl failed.\n");
-            goto out_cfg;
-        }
-        sched = rc;
-    }
-
-    if (libxl_get_freecpus(ctx, &freemap)) {
-        fprintf(stderr, "libxl_get_freecpus failed\n");
-        goto out_cfg;
-    }
-    if (libxl_cpu_bitmap_alloc(ctx, &cpumap, 0)) {
-        fprintf(stderr, "Failed to allocate cpumap\n");
-        goto out_cfg;
-    }
-    if (!xlu_cfg_get_list(config, "nodes", &nodes, 0, 0)) {
-        int nr;
-        n_cpus = 0;
-        n_nodes = 0;
-        topology = libxl_get_cpu_topology(ctx, &nr);
-        if (topology == NULL) {
-            fprintf(stderr, "libxl_get_topologyinfo failed\n");
-            goto out_cfg;
-        }
-        while ((buf = xlu_cfg_get_listitem(nodes, n_nodes)) != NULL) {
-            n = atoi(buf);
-            for (i = 0; i < nr; i++) {
-                if ((topology[i].node == n) &&
-                    libxl_bitmap_test(&freemap, i)) {
-                    libxl_bitmap_set(&cpumap, i);
-                    n_cpus++;
-                }
-            }
-            n_nodes++;
-        }
-
-        libxl_cputopology_list_free(topology, nr);
-
-        if (n_cpus == 0) {
-            fprintf(stderr, "no free cpu found\n");
-            goto out_cfg;
-        }
-    } else if (!xlu_cfg_get_list(config, "cpus", &cpus, 0, 1)) {
-        n_cpus = 0;
-        while ((buf = xlu_cfg_get_listitem(cpus, n_cpus)) != NULL) {
-            i = atoi(buf);
-            if ((i < 0) || !libxl_bitmap_test(&freemap, i)) {
-                fprintf(stderr, "cpu %d illegal or not free\n", i);
-                goto out_cfg;
-            }
-            libxl_bitmap_set(&cpumap, i);
-            n_cpus++;
-        }
-    } else if (!xlu_cfg_get_string(config, "cpus", &buf, 0)) {
-        if (parse_cpurange(buf, &cpumap))
-            goto out_cfg;
-
-        n_cpus = 0;
-        libxl_for_each_set_bit(i, cpumap) {
-            if (!libxl_bitmap_test(&freemap, i)) {
-                fprintf(stderr, "cpu %d illegal or not free\n", i);
-                goto out_cfg;
-            }
-            n_cpus++;
-        }
-    } else
-        n_cpus = 0;
-
-    libxl_uuid_generate(&uuid);
-
-    printf("Using config file \"%s\"\n", config_src);
-    printf("cpupool name:   %s\n", name);
-    printf("scheduler:      %s\n", libxl_scheduler_to_string(sched));
-    printf("number of cpus: %d\n", n_cpus);
-
-    if (!dryrun_only) {
-        poolid = LIBXL_CPUPOOL_POOLID_ANY;
-        if (libxl_cpupool_create(ctx, name, sched, cpumap, &uuid, &poolid)) {
-            fprintf(stderr, "error on creating cpupool\n");
-            goto out_cfg;
-        }
-    }
-    /* We made it! */
-    rc = EXIT_SUCCESS;
-
-out_cfg:
-    xlu_cfg_destroy(config);
-out:
-    libxl_bitmap_dispose(&freemap);
-    libxl_bitmap_dispose(&cpumap);
-    free(name);
-    free(config_data);
-    free(extra_config);
-    return rc;
-}
-
-int main_cpupoollist(int argc, char **argv)
-{
-    int opt;
-    static struct option opts[] = {
-        {"cpus", 0, 0, 'c'},
-        COMMON_LONG_OPTS
-    };
-    int opt_cpus = 0;
-    const char *pool = NULL;
-    libxl_cpupoolinfo *poolinfo;
-    int n_pools, p, c, n;
-    uint32_t poolid;
-    char *name;
-
-    SWITCH_FOREACH_OPT(opt, "c", opts, "cpupool-list", 0) {
-    case 'c':
-        opt_cpus = 1;
-        break;
-    }
-
-    if (optind < argc) {
-        pool = argv[optind];
-        if (libxl_name_to_cpupoolid(ctx, pool, &poolid)) {
-            fprintf(stderr, "Pool \'%s\' does not exist\n", pool);
-            return EXIT_FAILURE;
-        }
-    }
-
-    poolinfo = libxl_list_cpupool(ctx, &n_pools);
-    if (!poolinfo) {
-        fprintf(stderr, "error getting cpupool info\n");
-        return EXIT_FAILURE;
-    }
-
-    printf("%-19s", "Name");
-    if (opt_cpus)
-        printf("CPU list\n");
-    else
-        printf("CPUs   Sched     Active   Domain count\n");
-
-    for (p = 0; p < n_pools; p++) {
-        if (!pool || (poolinfo[p].poolid == poolid)) {
-            name = poolinfo[p].pool_name;
-            printf("%-19s", name);
-            n = 0;
-            libxl_for_each_bit(c, poolinfo[p].cpumap)
-                if (libxl_bitmap_test(&poolinfo[p].cpumap, c)) {
-                    if (n && opt_cpus) printf(",");
-                    if (opt_cpus) printf("%d", c);
-                    n++;
-                }
-            if (!opt_cpus) {
-                printf("%3d %9s       y       %4d", n,
-                       libxl_scheduler_to_string(poolinfo[p].sched),
-                       poolinfo[p].n_dom);
-            }
-            printf("\n");
-        }
-    }
-
-    libxl_cpupoolinfo_list_free(poolinfo, n_pools);
-
-    return EXIT_SUCCESS;
-}
-
-int main_cpupooldestroy(int argc, char **argv)
-{
-    int opt;
-    const char *pool;
-    uint32_t poolid;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-destroy", 1) {
-        /* No options */
-    }
-
-    pool = argv[optind];
-
-    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
-        !libxl_cpupoolid_is_valid(ctx, poolid)) {
-        fprintf(stderr, "unknown cpupool '%s'\n", pool);
-        return EXIT_FAILURE;
-    }
-
-    if (libxl_cpupool_destroy(ctx, poolid)) {
-        fprintf(stderr, "Can't destroy cpupool '%s'\n", pool);
-        return EXIT_FAILURE;
-    }
-
-    return EXIT_SUCCESS;
-}
-
-int main_cpupoolrename(int argc, char **argv)
-{
-    int opt;
-    const char *pool;
-    const char *new_name;
-    uint32_t poolid;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-rename", 2) {
-        /* No options */
-    }
-
-    pool = argv[optind++];
-
-    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
-        !libxl_cpupoolid_is_valid(ctx, poolid)) {
-        fprintf(stderr, "unknown cpupool '%s'\n", pool);
-        return EXIT_FAILURE;
-    }
-
-    new_name = argv[optind];
-
-    if (libxl_cpupool_rename(ctx, new_name, poolid)) {
-        fprintf(stderr, "Can't rename cpupool '%s'\n", pool);
-        return EXIT_FAILURE;
-    }
-
-    return EXIT_SUCCESS;
-}
-
-int main_cpupoolcpuadd(int argc, char **argv)
-{
-    int opt;
-    const char *pool;
-    uint32_t poolid;
-    libxl_bitmap cpumap;
-    int rc = EXIT_FAILURE;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-cpu-add", 2) {
-        /* No options */
-    }
-
-    libxl_bitmap_init(&cpumap);
-    if (libxl_cpu_bitmap_alloc(ctx, &cpumap, 0)) {
-        fprintf(stderr, "Unable to allocate cpumap");
-        return EXIT_FAILURE;
-    }
-
-    pool = argv[optind++];
-    if (parse_cpurange(argv[optind], &cpumap))
-        goto out;
-
-    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
-        !libxl_cpupoolid_is_valid(ctx, poolid)) {
-        fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
-        goto out;
-    }
-
-    if (libxl_cpupool_cpuadd_cpumap(ctx, poolid, &cpumap))
-        fprintf(stderr, "some cpus may not have been added to %s\n", pool);
-
-    rc = EXIT_SUCCESS;
-
-out:
-    libxl_bitmap_dispose(&cpumap);
-    return rc;
-}
-
-int main_cpupoolcpuremove(int argc, char **argv)
-{
-    int opt;
-    const char *pool;
-    uint32_t poolid;
-    libxl_bitmap cpumap;
-    int rc = EXIT_FAILURE;
-
-    libxl_bitmap_init(&cpumap);
-    if (libxl_cpu_bitmap_alloc(ctx, &cpumap, 0)) {
-        fprintf(stderr, "Unable to allocate cpumap");
-        return EXIT_FAILURE;
-    }
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-cpu-remove", 2) {
-        /* No options */
-    }
-
-    pool = argv[optind++];
-    if (parse_cpurange(argv[optind], &cpumap))
-        goto out;
-
-    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
-        !libxl_cpupoolid_is_valid(ctx, poolid)) {
-        fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
-        goto out;
-    }
-
-    if (libxl_cpupool_cpuremove_cpumap(ctx, poolid, &cpumap)) {
-        fprintf(stderr, "Some cpus may have not or only partially been removed from '%s'.\n", pool);
-        fprintf(stderr, "If a cpu can't be added to another cpupool, add it to '%s' again and retry.\n", pool);
-    }
-
-    rc = EXIT_SUCCESS;
-
-out:
-    libxl_bitmap_dispose(&cpumap);
-    return rc;
-}
-
-int main_cpupoolmigrate(int argc, char **argv)
-{
-    int opt;
-    const char *pool;
-    uint32_t poolid;
-    const char *dom;
-    uint32_t domid;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-migrate", 2) {
-        /* No options */
-    }
-
-    dom = argv[optind++];
-    pool = argv[optind];
-
-    if (libxl_domain_qualifier_to_domid(ctx, dom, &domid) ||
-        !libxl_domid_to_name(ctx, domid)) {
-        fprintf(stderr, "unknown domain '%s'\n", dom);
-        return EXIT_FAILURE;
-    }
-
-    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
-        !libxl_cpupoolid_is_valid(ctx, poolid)) {
-        fprintf(stderr, "unknown cpupool '%s'\n", pool);
-        return EXIT_FAILURE;
-    }
-
-    if (libxl_cpupool_movedomain(ctx, poolid, domid))
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-int main_cpupoolnumasplit(int argc, char **argv)
-{
-    int rc;
-    int opt;
-    int p;
-    int c;
-    int n;
-    uint32_t poolid;
-    libxl_scheduler sched;
-    int n_pools;
-    int node;
-    int n_cpus;
-    char *name = NULL;
-    libxl_uuid uuid;
-    libxl_bitmap cpumap;
-    libxl_cpupoolinfo *poolinfo;
-    libxl_cputopology *topology;
-    libxl_dominfo info;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-numa-split", 0) {
-        /* No options */
-    }
-
-    libxl_dominfo_init(&info);
-
-    rc = EXIT_FAILURE;
-
-    libxl_bitmap_init(&cpumap);
-    poolinfo = libxl_list_cpupool(ctx, &n_pools);
-    if (!poolinfo) {
-        fprintf(stderr, "error getting cpupool info\n");
-        return EXIT_FAILURE;
-    }
-    poolid = poolinfo[0].poolid;
-    sched = poolinfo[0].sched;
-    libxl_cpupoolinfo_list_free(poolinfo, n_pools);
-
-    if (n_pools > 1) {
-        fprintf(stderr, "splitting not possible, already cpupools in use\n");
-        return EXIT_FAILURE;
-    }
-
-    topology = libxl_get_cpu_topology(ctx, &n_cpus);
-    if (topology == NULL) {
-        fprintf(stderr, "libxl_get_topologyinfo failed\n");
-        return EXIT_FAILURE;
-    }
-
-    if (libxl_cpu_bitmap_alloc(ctx, &cpumap, 0)) {
-        fprintf(stderr, "Failed to allocate cpumap\n");
-        goto out;
-    }
-
-    /* Reset Pool-0 to 1st node: first add cpus, then remove cpus to avoid
-       a cpupool without cpus in between */
-
-    node = topology[0].node;
-    if (libxl_cpupool_cpuadd_node(ctx, 0, node, &n)) {
-        fprintf(stderr, "error on adding cpu to Pool 0\n");
-        goto out;
-    }
-
-    xasprintf(&name, "Pool-node%d", node);
-    if (libxl_cpupool_rename(ctx, name, 0)) {
-        fprintf(stderr, "error on renaming Pool 0\n");
-        goto out;
-    }
-
-    n = 0;
-    for (c = 0; c < n_cpus; c++) {
-        if (topology[c].node == node) {
-            topology[c].node = LIBXL_CPUTOPOLOGY_INVALID_ENTRY;
-            libxl_bitmap_set(&cpumap, n);
-            n++;
-        }
-    }
-    if (libxl_domain_info(ctx, &info, 0)) {
-        fprintf(stderr, "error on getting info for Domain-0\n");
-        goto out;
-    }
-    if (info.vcpu_online > n && libxl_set_vcpuonline(ctx, 0, &cpumap)) {
-        fprintf(stderr, "error on removing vcpus for Domain-0\n");
-        goto out;
-    }
-    for (c = 0; c < 10; c++) {
-        /* We've called libxl_dominfo_init before the loop and will
-         * call libxl_dominfo_dispose after the loop when we're done
-         * with info.
-         */
-        libxl_dominfo_dispose(&info);
-        libxl_dominfo_init(&info);
-        if (libxl_domain_info(ctx, &info, 0)) {
-            fprintf(stderr, "error on getting info for Domain-0\n");
-            goto out;
-        }
-        if (info.vcpu_online <= n) {
-            break;
-        }
-        sleep(1);
-    }
-    if (info.vcpu_online > n) {
-        fprintf(stderr, "failed to offline vcpus\n");
-        goto out;
-    }
-    libxl_bitmap_set_none(&cpumap);
-
-    for (c = 0; c < n_cpus; c++) {
-        if (topology[c].node == LIBXL_CPUTOPOLOGY_INVALID_ENTRY) {
-            continue;
-        }
-
-        node = topology[c].node;
-        if (libxl_cpupool_cpuremove_node(ctx, 0, node, &n)) {
-            fprintf(stderr, "error on removing cpu from Pool 0\n");
-            goto out;
-        }
-
-        free(name);
-        xasprintf(&name, "Pool-node%d", node);
-        libxl_uuid_generate(&uuid);
-        poolid = 0;
-        if (libxl_cpupool_create(ctx, name, sched, cpumap, &uuid, &poolid)) {
-            fprintf(stderr, "error on creating cpupool\n");
-            goto out;
-        }
-
-        if (libxl_cpupool_cpuadd_node(ctx, poolid, node, &n)) {
-            fprintf(stderr, "error on adding cpus to cpupool\n");
-            goto out;
-        }
-
-        for (p = c; p < n_cpus; p++) {
-            if (topology[p].node == node) {
-                topology[p].node = LIBXL_CPUTOPOLOGY_INVALID_ENTRY;
-            }
-        }
-    }
-
-    rc = EXIT_SUCCESS;
-
-out:
-    libxl_cputopology_list_free(topology, n_cpus);
-    libxl_bitmap_dispose(&cpumap);
-    libxl_dominfo_dispose(&info);
-    free(name);
-
-    return rc;
-}
-
 int main_getenforce(int argc, char **argv)
 {
     int ret;
diff --git a/tools/xl/xl_cpupool.c b/tools/xl/xl_cpupool.c
new file mode 100644
index 0000000000..b0194644e9
--- /dev/null
+++ b/tools/xl/xl_cpupool.c
@@ -0,0 +1,624 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+int main_cpupoolcreate(int argc, char **argv)
+{
+    const char *filename = NULL, *config_src=NULL;
+    const char *p;
+    char *extra_config = NULL;
+    int opt;
+    static struct option opts[] = {
+        {"defconfig", 1, 0, 'f'},
+        {"dryrun", 0, 0, 'n'},
+        COMMON_LONG_OPTS
+    };
+    int ret;
+    char *config_data = 0;
+    int config_len = 0;
+    XLU_Config *config;
+    const char *buf;
+    char *name = NULL;
+    uint32_t poolid;
+    libxl_scheduler sched = 0;
+    XLU_ConfigList *cpus;
+    XLU_ConfigList *nodes;
+    int n_cpus, n_nodes, i, n;
+    libxl_bitmap freemap;
+    libxl_bitmap cpumap;
+    libxl_uuid uuid;
+    libxl_cputopology *topology;
+    int rc = EXIT_FAILURE;
+
+    SWITCH_FOREACH_OPT(opt, "nf:", opts, "cpupool-create", 0) {
+    case 'f':
+        filename = optarg;
+        break;
+    case 'n':
+        dryrun_only = 1;
+        break;
+    }
+
+    libxl_bitmap_init(&freemap);
+    libxl_bitmap_init(&cpumap);
+
+    while (optind < argc) {
+        if ((p = strchr(argv[optind], '='))) {
+            xstring_realloc_append(&extra_config, "\n");
+            xstring_realloc_append(&extra_config, argv[optind]);
+        } else if (!filename) {
+            filename = argv[optind];
+        } else {
+            help("cpupool-create");
+            goto out;
+        }
+        optind++;
+    }
+
+    if (filename)
+    {
+        if (libxl_read_file_contents(ctx, filename, (void **)&config_data,
+                                     &config_len)) {
+            fprintf(stderr, "Failed to read config file: %s: %s\n",
+                    filename, strerror(errno));
+            goto out;
+        }
+        config_src=filename;
+    }
+    else
+        config_src="command line";
+
+    if (extra_config && strlen(extra_config)) {
+        if (config_len > INT_MAX - (strlen(extra_config) + 2)) {
+            fprintf(stderr, "Failed to attach extra configuration\n");
+            goto out;
+        }
+        config_data = xrealloc(config_data,
+                               config_len + strlen(extra_config) + 2);
+        if (!config_data) {
+            fprintf(stderr, "Failed to realloc config_data\n");
+            goto out;
+        }
+        config_data[config_len] = 0;
+        strcat(config_data, extra_config);
+        strcat(config_data, "\n");
+        config_len += strlen(extra_config) + 1;
+    }
+
+    config = xlu_cfg_init(stderr, config_src);
+    if (!config) {
+        fprintf(stderr, "Failed to allocate for configuration\n");
+        goto out;
+    }
+
+    ret = xlu_cfg_readdata(config, config_data, config_len);
+    if (ret) {
+        fprintf(stderr, "Failed to parse config file: %s\n", strerror(ret));
+        goto out_cfg;
+    }
+
+    if (!xlu_cfg_get_string (config, "name", &buf, 0))
+        name = strdup(buf);
+    else if (filename)
+        name = libxl_basename(filename);
+    else {
+        fprintf(stderr, "Missing cpupool name!\n");
+        goto out_cfg;
+    }
+    if (!libxl_name_to_cpupoolid(ctx, name, &poolid)) {
+        fprintf(stderr, "Pool name \"%s\" already exists\n", name);
+        goto out_cfg;
+    }
+
+    if (!xlu_cfg_get_string (config, "sched", &buf, 0)) {
+        if ((libxl_scheduler_from_string(buf, &sched)) < 0) {
+            fprintf(stderr, "Unknown scheduler\n");
+            goto out_cfg;
+        }
+    } else {
+        rc = libxl_get_scheduler(ctx);
+        if (rc < 0) {
+            fprintf(stderr, "get_scheduler sysctl failed.\n");
+            goto out_cfg;
+        }
+        sched = rc;
+    }
+
+    if (libxl_get_freecpus(ctx, &freemap)) {
+        fprintf(stderr, "libxl_get_freecpus failed\n");
+        goto out_cfg;
+    }
+    if (libxl_cpu_bitmap_alloc(ctx, &cpumap, 0)) {
+        fprintf(stderr, "Failed to allocate cpumap\n");
+        goto out_cfg;
+    }
+    if (!xlu_cfg_get_list(config, "nodes", &nodes, 0, 0)) {
+        int nr;
+        n_cpus = 0;
+        n_nodes = 0;
+        topology = libxl_get_cpu_topology(ctx, &nr);
+        if (topology == NULL) {
+            fprintf(stderr, "libxl_get_topologyinfo failed\n");
+            goto out_cfg;
+        }
+        while ((buf = xlu_cfg_get_listitem(nodes, n_nodes)) != NULL) {
+            n = atoi(buf);
+            for (i = 0; i < nr; i++) {
+                if ((topology[i].node == n) &&
+                    libxl_bitmap_test(&freemap, i)) {
+                    libxl_bitmap_set(&cpumap, i);
+                    n_cpus++;
+                }
+            }
+            n_nodes++;
+        }
+
+        libxl_cputopology_list_free(topology, nr);
+
+        if (n_cpus == 0) {
+            fprintf(stderr, "no free cpu found\n");
+            goto out_cfg;
+        }
+    } else if (!xlu_cfg_get_list(config, "cpus", &cpus, 0, 1)) {
+        n_cpus = 0;
+        while ((buf = xlu_cfg_get_listitem(cpus, n_cpus)) != NULL) {
+            i = atoi(buf);
+            if ((i < 0) || !libxl_bitmap_test(&freemap, i)) {
+                fprintf(stderr, "cpu %d illegal or not free\n", i);
+                goto out_cfg;
+            }
+            libxl_bitmap_set(&cpumap, i);
+            n_cpus++;
+        }
+    } else if (!xlu_cfg_get_string(config, "cpus", &buf, 0)) {
+        if (parse_cpurange(buf, &cpumap))
+            goto out_cfg;
+
+        n_cpus = 0;
+        libxl_for_each_set_bit(i, cpumap) {
+            if (!libxl_bitmap_test(&freemap, i)) {
+                fprintf(stderr, "cpu %d illegal or not free\n", i);
+                goto out_cfg;
+            }
+            n_cpus++;
+        }
+    } else
+        n_cpus = 0;
+
+    libxl_uuid_generate(&uuid);
+
+    printf("Using config file \"%s\"\n", config_src);
+    printf("cpupool name:   %s\n", name);
+    printf("scheduler:      %s\n", libxl_scheduler_to_string(sched));
+    printf("number of cpus: %d\n", n_cpus);
+
+    if (!dryrun_only) {
+        poolid = LIBXL_CPUPOOL_POOLID_ANY;
+        if (libxl_cpupool_create(ctx, name, sched, cpumap, &uuid, &poolid)) {
+            fprintf(stderr, "error on creating cpupool\n");
+            goto out_cfg;
+        }
+    }
+    /* We made it! */
+    rc = EXIT_SUCCESS;
+
+out_cfg:
+    xlu_cfg_destroy(config);
+out:
+    libxl_bitmap_dispose(&freemap);
+    libxl_bitmap_dispose(&cpumap);
+    free(name);
+    free(config_data);
+    free(extra_config);
+    return rc;
+}
+
+int main_cpupoollist(int argc, char **argv)
+{
+    int opt;
+    static struct option opts[] = {
+        {"cpus", 0, 0, 'c'},
+        COMMON_LONG_OPTS
+    };
+    int opt_cpus = 0;
+    const char *pool = NULL;
+    libxl_cpupoolinfo *poolinfo;
+    int n_pools, p, c, n;
+    uint32_t poolid;
+    char *name;
+
+    SWITCH_FOREACH_OPT(opt, "c", opts, "cpupool-list", 0) {
+    case 'c':
+        opt_cpus = 1;
+        break;
+    }
+
+    if (optind < argc) {
+        pool = argv[optind];
+        if (libxl_name_to_cpupoolid(ctx, pool, &poolid)) {
+            fprintf(stderr, "Pool \'%s\' does not exist\n", pool);
+            return EXIT_FAILURE;
+        }
+    }
+
+    poolinfo = libxl_list_cpupool(ctx, &n_pools);
+    if (!poolinfo) {
+        fprintf(stderr, "error getting cpupool info\n");
+        return EXIT_FAILURE;
+    }
+
+    printf("%-19s", "Name");
+    if (opt_cpus)
+        printf("CPU list\n");
+    else
+        printf("CPUs   Sched     Active   Domain count\n");
+
+    for (p = 0; p < n_pools; p++) {
+        if (!pool || (poolinfo[p].poolid == poolid)) {
+            name = poolinfo[p].pool_name;
+            printf("%-19s", name);
+            n = 0;
+            libxl_for_each_bit(c, poolinfo[p].cpumap)
+                if (libxl_bitmap_test(&poolinfo[p].cpumap, c)) {
+                    if (n && opt_cpus) printf(",");
+                    if (opt_cpus) printf("%d", c);
+                    n++;
+                }
+            if (!opt_cpus) {
+                printf("%3d %9s       y       %4d", n,
+                       libxl_scheduler_to_string(poolinfo[p].sched),
+                       poolinfo[p].n_dom);
+            }
+            printf("\n");
+        }
+    }
+
+    libxl_cpupoolinfo_list_free(poolinfo, n_pools);
+
+    return EXIT_SUCCESS;
+}
+
+int main_cpupooldestroy(int argc, char **argv)
+{
+    int opt;
+    const char *pool;
+    uint32_t poolid;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-destroy", 1) {
+        /* No options */
+    }
+
+    pool = argv[optind];
+
+    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
+        !libxl_cpupoolid_is_valid(ctx, poolid)) {
+        fprintf(stderr, "unknown cpupool '%s'\n", pool);
+        return EXIT_FAILURE;
+    }
+
+    if (libxl_cpupool_destroy(ctx, poolid)) {
+        fprintf(stderr, "Can't destroy cpupool '%s'\n", pool);
+        return EXIT_FAILURE;
+    }
+
+    return EXIT_SUCCESS;
+}
+
+int main_cpupoolrename(int argc, char **argv)
+{
+    int opt;
+    const char *pool;
+    const char *new_name;
+    uint32_t poolid;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-rename", 2) {
+        /* No options */
+    }
+
+    pool = argv[optind++];
+
+    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
+        !libxl_cpupoolid_is_valid(ctx, poolid)) {
+        fprintf(stderr, "unknown cpupool '%s'\n", pool);
+        return EXIT_FAILURE;
+    }
+
+    new_name = argv[optind];
+
+    if (libxl_cpupool_rename(ctx, new_name, poolid)) {
+        fprintf(stderr, "Can't rename cpupool '%s'\n", pool);
+        return EXIT_FAILURE;
+    }
+
+    return EXIT_SUCCESS;
+}
+
+int main_cpupoolcpuadd(int argc, char **argv)
+{
+    int opt;
+    const char *pool;
+    uint32_t poolid;
+    libxl_bitmap cpumap;
+    int rc = EXIT_FAILURE;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-cpu-add", 2) {
+        /* No options */
+    }
+
+    libxl_bitmap_init(&cpumap);
+    if (libxl_cpu_bitmap_alloc(ctx, &cpumap, 0)) {
+        fprintf(stderr, "Unable to allocate cpumap");
+        return EXIT_FAILURE;
+    }
+
+    pool = argv[optind++];
+    if (parse_cpurange(argv[optind], &cpumap))
+        goto out;
+
+    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
+        !libxl_cpupoolid_is_valid(ctx, poolid)) {
+        fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
+        goto out;
+    }
+
+    if (libxl_cpupool_cpuadd_cpumap(ctx, poolid, &cpumap))
+        fprintf(stderr, "some cpus may not have been added to %s\n", pool);
+
+    rc = EXIT_SUCCESS;
+
+out:
+    libxl_bitmap_dispose(&cpumap);
+    return rc;
+}
+
+int main_cpupoolcpuremove(int argc, char **argv)
+{
+    int opt;
+    const char *pool;
+    uint32_t poolid;
+    libxl_bitmap cpumap;
+    int rc = EXIT_FAILURE;
+
+    libxl_bitmap_init(&cpumap);
+    if (libxl_cpu_bitmap_alloc(ctx, &cpumap, 0)) {
+        fprintf(stderr, "Unable to allocate cpumap");
+        return EXIT_FAILURE;
+    }
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-cpu-remove", 2) {
+        /* No options */
+    }
+
+    pool = argv[optind++];
+    if (parse_cpurange(argv[optind], &cpumap))
+        goto out;
+
+    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
+        !libxl_cpupoolid_is_valid(ctx, poolid)) {
+        fprintf(stderr, "unknown cpupool \'%s\'\n", pool);
+        goto out;
+    }
+
+    if (libxl_cpupool_cpuremove_cpumap(ctx, poolid, &cpumap)) {
+        fprintf(stderr, "Some cpus may have not or only partially been removed from '%s'.\n", pool);
+        fprintf(stderr, "If a cpu can't be added to another cpupool, add it to '%s' again and retry.\n", pool);
+    }
+
+    rc = EXIT_SUCCESS;
+
+out:
+    libxl_bitmap_dispose(&cpumap);
+    return rc;
+}
+
+int main_cpupoolmigrate(int argc, char **argv)
+{
+    int opt;
+    const char *pool;
+    uint32_t poolid;
+    const char *dom;
+    uint32_t domid;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-migrate", 2) {
+        /* No options */
+    }
+
+    dom = argv[optind++];
+    pool = argv[optind];
+
+    if (libxl_domain_qualifier_to_domid(ctx, dom, &domid) ||
+        !libxl_domid_to_name(ctx, domid)) {
+        fprintf(stderr, "unknown domain '%s'\n", dom);
+        return EXIT_FAILURE;
+    }
+
+    if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
+        !libxl_cpupoolid_is_valid(ctx, poolid)) {
+        fprintf(stderr, "unknown cpupool '%s'\n", pool);
+        return EXIT_FAILURE;
+    }
+
+    if (libxl_cpupool_movedomain(ctx, poolid, domid))
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+int main_cpupoolnumasplit(int argc, char **argv)
+{
+    int rc;
+    int opt;
+    int p;
+    int c;
+    int n;
+    uint32_t poolid;
+    libxl_scheduler sched;
+    int n_pools;
+    int node;
+    int n_cpus;
+    char *name = NULL;
+    libxl_uuid uuid;
+    libxl_bitmap cpumap;
+    libxl_cpupoolinfo *poolinfo;
+    libxl_cputopology *topology;
+    libxl_dominfo info;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "cpupool-numa-split", 0) {
+        /* No options */
+    }
+
+    libxl_dominfo_init(&info);
+
+    rc = EXIT_FAILURE;
+
+    libxl_bitmap_init(&cpumap);
+    poolinfo = libxl_list_cpupool(ctx, &n_pools);
+    if (!poolinfo) {
+        fprintf(stderr, "error getting cpupool info\n");
+        return EXIT_FAILURE;
+    }
+    poolid = poolinfo[0].poolid;
+    sched = poolinfo[0].sched;
+    libxl_cpupoolinfo_list_free(poolinfo, n_pools);
+
+    if (n_pools > 1) {
+        fprintf(stderr, "splitting not possible, already cpupools in use\n");
+        return EXIT_FAILURE;
+    }
+
+    topology = libxl_get_cpu_topology(ctx, &n_cpus);
+    if (topology == NULL) {
+        fprintf(stderr, "libxl_get_topologyinfo failed\n");
+        return EXIT_FAILURE;
+    }
+
+    if (libxl_cpu_bitmap_alloc(ctx, &cpumap, 0)) {
+        fprintf(stderr, "Failed to allocate cpumap\n");
+        goto out;
+    }
+
+    /* Reset Pool-0 to 1st node: first add cpus, then remove cpus to avoid
+       a cpupool without cpus in between */
+
+    node = topology[0].node;
+    if (libxl_cpupool_cpuadd_node(ctx, 0, node, &n)) {
+        fprintf(stderr, "error on adding cpu to Pool 0\n");
+        goto out;
+    }
+
+    xasprintf(&name, "Pool-node%d", node);
+    if (libxl_cpupool_rename(ctx, name, 0)) {
+        fprintf(stderr, "error on renaming Pool 0\n");
+        goto out;
+    }
+
+    n = 0;
+    for (c = 0; c < n_cpus; c++) {
+        if (topology[c].node == node) {
+            topology[c].node = LIBXL_CPUTOPOLOGY_INVALID_ENTRY;
+            libxl_bitmap_set(&cpumap, n);
+            n++;
+        }
+    }
+    if (libxl_domain_info(ctx, &info, 0)) {
+        fprintf(stderr, "error on getting info for Domain-0\n");
+        goto out;
+    }
+    if (info.vcpu_online > n && libxl_set_vcpuonline(ctx, 0, &cpumap)) {
+        fprintf(stderr, "error on removing vcpus for Domain-0\n");
+        goto out;
+    }
+    for (c = 0; c < 10; c++) {
+        /* We've called libxl_dominfo_init before the loop and will
+         * call libxl_dominfo_dispose after the loop when we're done
+         * with info.
+         */
+        libxl_dominfo_dispose(&info);
+        libxl_dominfo_init(&info);
+        if (libxl_domain_info(ctx, &info, 0)) {
+            fprintf(stderr, "error on getting info for Domain-0\n");
+            goto out;
+        }
+        if (info.vcpu_online <= n) {
+            break;
+        }
+        sleep(1);
+    }
+    if (info.vcpu_online > n) {
+        fprintf(stderr, "failed to offline vcpus\n");
+        goto out;
+    }
+    libxl_bitmap_set_none(&cpumap);
+
+    for (c = 0; c < n_cpus; c++) {
+        if (topology[c].node == LIBXL_CPUTOPOLOGY_INVALID_ENTRY) {
+            continue;
+        }
+
+        node = topology[c].node;
+        if (libxl_cpupool_cpuremove_node(ctx, 0, node, &n)) {
+            fprintf(stderr, "error on removing cpu from Pool 0\n");
+            goto out;
+        }
+
+        free(name);
+        xasprintf(&name, "Pool-node%d", node);
+        libxl_uuid_generate(&uuid);
+        poolid = 0;
+        if (libxl_cpupool_create(ctx, name, sched, cpumap, &uuid, &poolid)) {
+            fprintf(stderr, "error on creating cpupool\n");
+            goto out;
+        }
+
+        if (libxl_cpupool_cpuadd_node(ctx, poolid, node, &n)) {
+            fprintf(stderr, "error on adding cpus to cpupool\n");
+            goto out;
+        }
+
+        for (p = c; p < n_cpus; p++) {
+            if (topology[p].node == node) {
+                topology[p].node = LIBXL_CPUTOPOLOGY_INVALID_ENTRY;
+            }
+        }
+    }
+
+    rc = EXIT_SUCCESS;
+
+out:
+    libxl_cputopology_list_free(topology, n_cpus);
+    libxl_bitmap_dispose(&cpumap);
+    libxl_dominfo_dispose(&info);
+    free(name);
+
+    return rc;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 12/29] xl: split out flask related code
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (10 preceding siblings ...)
  2017-02-24 16:12 ` [PATCH 11/29] xl: split out cpupool related code Wei Liu
@ 2017-02-24 16:12 ` Wei Liu
  2017-02-27 16:01   ` Ian Jackson
  2017-02-24 16:12 ` [PATCH 13/29] xl: split out vtpm " Wei Liu
                   ` (16 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:12 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   2 +-
 tools/xl/xl_cmdimpl.c | 119 ---------------------------------------
 tools/xl/xl_flask.c   | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 154 insertions(+), 120 deletions(-)
 create mode 100644 tools/xl/xl_flask.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index 0ff7ef9bfe..df0b5dd5cf 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -16,7 +16,7 @@ CFLAGS_XL += $(CFLAGS_libxenlight)
 CFLAGS_XL += -Wshadow
 
 XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
-XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o
+XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index 82b30bb094..eb87cb975a 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -5611,125 +5611,6 @@ int main_uptime(int argc, char **argv)
     return 0;
 }
 
-int main_getenforce(int argc, char **argv)
-{
-    int ret;
-
-    ret = libxl_flask_getenforce(ctx);
-
-    if (ret < 0) {
-        if (errno == ENOSYS)
-            printf("Flask XSM Disabled\n");
-        else
-            fprintf(stderr, "Failed to get enforcing mode\n");
-    }
-    else if (ret == 1)
-        printf("Enforcing\n");
-    else if (ret == 0)
-        printf("Permissive\n");
-
-    return ret;
-}
-
-int main_setenforce(int argc, char **argv)
-{
-    int ret, mode;
-    const char *p = NULL;
-
-    if (optind >= argc) {
-        help("setenforce");
-        return 2;
-    }
-
-    p = argv[optind];
-
-    if (!strcmp(p, "0"))
-        mode = 0;
-    else if (!strcmp(p, "1"))
-        mode = 1;
-    else if (!strcasecmp(p, "permissive"))
-        mode = 0;
-    else if (!strcasecmp(p, "enforcing"))
-        mode = 1;
-    else {
-        help("setenforce");
-        return 2;
-    }
-
-    ret = libxl_flask_setenforce(ctx, mode);
-
-    if (ret) {
-        if (errno == ENOSYS) {
-            fprintf(stderr, "Flask XSM disabled\n");
-        }
-        else
-            fprintf(stderr, "error occured while setting enforcing mode (%i)\n", ret);
-    }
-
-    return ret;
-}
-
-int main_loadpolicy(int argc, char **argv)
-{
-    const char *polFName;
-    int polFd = -1;
-    void *polMemCp = NULL;
-    struct stat info;
-    int ret;
-
-    if (optind >= argc) {
-        help("loadpolicy");
-        return 2;
-    }
-
-    polFName = argv[optind];
-    polFd = open(polFName, O_RDONLY);
-    if (polFd < 0) {
-        fprintf(stderr, "Error occurred opening policy file '%s': %s\n",
-                polFName, strerror(errno));
-        ret = -1;
-        goto done;
-    }
-
-    ret = stat(polFName, &info);
-    if (ret < 0) {
-        fprintf(stderr, "Error occurred retrieving information about"
-                "policy file '%s': %s\n", polFName, strerror(errno));
-        goto done;
-    }
-
-    polMemCp = malloc(info.st_size);
-
-    ret = read(polFd, polMemCp, info.st_size);
-    if ( ret < 0 ) {
-        fprintf(stderr, "Unable to read new Flask policy file: %s\n",
-                strerror(errno));
-        goto done;
-    }
-
-    ret = libxl_flask_loadpolicy(ctx, polMemCp, info.st_size);
-
-    if (ret < 0) {
-        if (errno == ENOSYS) {
-            fprintf(stderr, "Flask XSM disabled\n");
-        } else {
-            errno = -ret;
-            fprintf(stderr, "Unable to load new Flask policy: %s\n",
-                    strerror(errno));
-            ret = -1;
-        }
-    } else {
-        printf("Successfully loaded policy.\n");
-    }
-
-done:
-    free(polMemCp);
-    if (polFd >= 0)
-        close(polFd);
-
-    return ret;
-}
-
 #ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
 int main_remus(int argc, char **argv)
 {
diff --git a/tools/xl/xl_flask.c b/tools/xl/xl_flask.c
new file mode 100644
index 0000000000..804165c6a8
--- /dev/null
+++ b/tools/xl/xl_flask.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <libxl.h>
+
+#include "xl.h"
+
+extern libxl_ctx *ctx;
+
+int main_getenforce(int argc, char **argv)
+{
+    int ret;
+
+    ret = libxl_flask_getenforce(ctx);
+
+    if (ret < 0) {
+        if (errno == ENOSYS)
+            printf("Flask XSM Disabled\n");
+        else
+            fprintf(stderr, "Failed to get enforcing mode\n");
+    }
+    else if (ret == 1)
+        printf("Enforcing\n");
+    else if (ret == 0)
+        printf("Permissive\n");
+
+    return ret;
+}
+
+int main_setenforce(int argc, char **argv)
+{
+    int ret, mode;
+    const char *p = NULL;
+
+    if (optind >= argc) {
+        help("setenforce");
+        return 2;
+    }
+
+    p = argv[optind];
+
+    if (!strcmp(p, "0"))
+        mode = 0;
+    else if (!strcmp(p, "1"))
+        mode = 1;
+    else if (!strcasecmp(p, "permissive"))
+        mode = 0;
+    else if (!strcasecmp(p, "enforcing"))
+        mode = 1;
+    else {
+        help("setenforce");
+        return 2;
+    }
+
+    ret = libxl_flask_setenforce(ctx, mode);
+
+    if (ret) {
+        if (errno == ENOSYS) {
+            fprintf(stderr, "Flask XSM disabled\n");
+        }
+        else
+            fprintf(stderr, "error occured while setting enforcing mode (%i)\n", ret);
+    }
+
+    return ret;
+}
+
+int main_loadpolicy(int argc, char **argv)
+{
+    const char *polFName;
+    int polFd = -1;
+    void *polMemCp = NULL;
+    struct stat info;
+    int ret;
+
+    if (optind >= argc) {
+        help("loadpolicy");
+        return 2;
+    }
+
+    polFName = argv[optind];
+    polFd = open(polFName, O_RDONLY);
+    if (polFd < 0) {
+        fprintf(stderr, "Error occurred opening policy file '%s': %s\n",
+                polFName, strerror(errno));
+        ret = -1;
+        goto done;
+    }
+
+    ret = stat(polFName, &info);
+    if (ret < 0) {
+        fprintf(stderr, "Error occurred retrieving information about"
+                "policy file '%s': %s\n", polFName, strerror(errno));
+        goto done;
+    }
+
+    polMemCp = malloc(info.st_size);
+
+    ret = read(polFd, polMemCp, info.st_size);
+    if ( ret < 0 ) {
+        fprintf(stderr, "Unable to read new Flask policy file: %s\n",
+                strerror(errno));
+        goto done;
+    }
+
+    ret = libxl_flask_loadpolicy(ctx, polMemCp, info.st_size);
+
+    if (ret < 0) {
+        if (errno == ENOSYS) {
+            fprintf(stderr, "Flask XSM disabled\n");
+        } else {
+            errno = -ret;
+            fprintf(stderr, "Unable to load new Flask policy: %s\n",
+                    strerror(errno));
+            ret = -1;
+        }
+    } else {
+        printf("Successfully loaded policy.\n");
+    }
+
+done:
+    free(polMemCp);
+    if (polFd >= 0)
+        close(polFd);
+
+    return ret;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 13/29] xl: split out vtpm related code
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (11 preceding siblings ...)
  2017-02-24 16:12 ` [PATCH 12/29] xl: split out flask " Wei Liu
@ 2017-02-24 16:12 ` Wei Liu
  2017-02-27 15:55   ` Ian Jackson
  2017-02-24 16:12 ` [PATCH 14/29] xl: split out block " Wei Liu
                   ` (15 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:12 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   1 +
 tools/xl/xl_cmdimpl.c | 122 ----------------------------------------
 tools/xl/xl_vtpm.c    | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 154 insertions(+), 122 deletions(-)
 create mode 100644 tools/xl/xl_vtpm.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index df0b5dd5cf..b31ec052c1 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -17,6 +17,7 @@ CFLAGS_XL += -Wshadow
 
 XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
 XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
+XL_OBJS += xl_vtpm.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index eb87cb975a..aeb4fb362f 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -5274,128 +5274,6 @@ int main_blockdetach(int argc, char **argv)
     return rc;
 }
 
-int main_vtpmattach(int argc, char **argv)
-{
-    int opt;
-    libxl_device_vtpm vtpm;
-    char *oparg;
-    uint32_t domid;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "vtpm-attach", 1) {
-        /* No options */
-    }
-
-    if (libxl_domain_qualifier_to_domid(ctx, argv[optind], &domid) < 0) {
-        fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
-        return 1;
-    }
-    ++optind;
-
-    libxl_device_vtpm_init(&vtpm);
-    for (argv += optind, argc -= optind; argc > 0; ++argv, --argc) {
-        if (MATCH_OPTION("uuid", *argv, oparg)) {
-            if(libxl_uuid_from_string(&(vtpm.uuid), oparg)) {
-                fprintf(stderr, "Invalid uuid specified (%s)\n", oparg);
-                return 1;
-            }
-        } else if (MATCH_OPTION("backend", *argv, oparg)) {
-            replace_string(&vtpm.backend_domname, oparg);
-        } else {
-            fprintf(stderr, "unrecognized argument `%s'\n", *argv);
-            return 1;
-        }
-    }
-
-    if(dryrun_only) {
-       char* json = libxl_device_vtpm_to_json(ctx, &vtpm);
-       printf("vtpm: %s\n", json);
-       free(json);
-       libxl_device_vtpm_dispose(&vtpm);
-       if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
-       return 0;
-    }
-
-    if (libxl_device_vtpm_add(ctx, domid, &vtpm, 0)) {
-        fprintf(stderr, "libxl_device_vtpm_add failed.\n");
-        return 1;
-    }
-    libxl_device_vtpm_dispose(&vtpm);
-    return 0;
-}
-
-int main_vtpmlist(int argc, char **argv)
-{
-    int opt;
-    libxl_device_vtpm *vtpms;
-    libxl_vtpminfo vtpminfo;
-    int nb, i;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "vtpm-list", 1) {
-        /* No options */
-    }
-
-    /*      Idx  BE   UUID   Hdl  Sta  evch rref  BE-path */
-    printf("%-3s %-2s %-36s %-6s %-5s %-6s %-5s %-10s\n",
-           "Idx", "BE", "Uuid", "handle", "state", "evt-ch", "ring-ref", "BE-path");
-    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
-        uint32_t domid;
-        if (libxl_domain_qualifier_to_domid(ctx, *argv, &domid) < 0) {
-            fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
-            continue;
-        }
-        if (!(vtpms = libxl_device_vtpm_list(ctx, domid, &nb))) {
-            continue;
-        }
-        for (i = 0; i < nb; ++i) {
-           if(!libxl_device_vtpm_getinfo(ctx, domid, &vtpms[i], &vtpminfo)) {
-              /*      Idx  BE     UUID             Hdl Sta evch rref BE-path*/
-              printf("%-3d %-2d " LIBXL_UUID_FMT " %6d %5d %6d %8d %-30s\n",
-                    vtpminfo.devid, vtpminfo.backend_id,
-                    LIBXL_UUID_BYTES(vtpminfo.uuid),
-                    vtpminfo.devid, vtpminfo.state, vtpminfo.evtch,
-                    vtpminfo.rref, vtpminfo.backend);
-
-              libxl_vtpminfo_dispose(&vtpminfo);
-           }
-           libxl_device_vtpm_dispose(&vtpms[i]);
-        }
-        free(vtpms);
-    }
-    return 0;
-}
-
-int main_vtpmdetach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt, rc=0;
-    libxl_device_vtpm vtpm;
-    libxl_uuid uuid;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "vtpm-detach", 2) {
-        /* No options */
-    }
-
-    domid = xfind_domain(argv[optind]);
-
-    if ( libxl_uuid_from_string(&uuid, argv[optind+1])) {
-        if (libxl_devid_to_device_vtpm(ctx, domid, atoi(argv[optind+1]), &vtpm)) {
-            fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
-            return 1;
-        }
-    } else {
-        if (libxl_uuid_to_device_vtpm(ctx, domid, &uuid, &vtpm)) {
-            fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
-            return 1;
-        }
-    }
-    rc = libxl_device_vtpm_remove(ctx, domid, &vtpm, 0);
-    if (rc) {
-        fprintf(stderr, "libxl_device_vtpm_remove failed.\n");
-    }
-    libxl_device_vtpm_dispose(&vtpm);
-    return rc;
-}
-
 
 static char *uptime_to_string(unsigned long uptime, int short_mode)
 {
diff --git a/tools/xl/xl_vtpm.c b/tools/xl/xl_vtpm.c
new file mode 100644
index 0000000000..a69cc04eff
--- /dev/null
+++ b/tools/xl/xl_vtpm.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <stdlib.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+int main_vtpmattach(int argc, char **argv)
+{
+    int opt;
+    libxl_device_vtpm vtpm;
+    char *oparg;
+    uint32_t domid;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vtpm-attach", 1) {
+        /* No options */
+    }
+
+    if (libxl_domain_qualifier_to_domid(ctx, argv[optind], &domid) < 0) {
+        fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
+        return 1;
+    }
+    ++optind;
+
+    libxl_device_vtpm_init(&vtpm);
+    for (argv += optind, argc -= optind; argc > 0; ++argv, --argc) {
+        if (MATCH_OPTION("uuid", *argv, oparg)) {
+            if(libxl_uuid_from_string(&(vtpm.uuid), oparg)) {
+                fprintf(stderr, "Invalid uuid specified (%s)\n", oparg);
+                return 1;
+            }
+        } else if (MATCH_OPTION("backend", *argv, oparg)) {
+            replace_string(&vtpm.backend_domname, oparg);
+        } else {
+            fprintf(stderr, "unrecognized argument `%s'\n", *argv);
+            return 1;
+        }
+    }
+
+    if(dryrun_only) {
+       char* json = libxl_device_vtpm_to_json(ctx, &vtpm);
+       printf("vtpm: %s\n", json);
+       free(json);
+       libxl_device_vtpm_dispose(&vtpm);
+       if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
+       return 0;
+    }
+
+    if (libxl_device_vtpm_add(ctx, domid, &vtpm, 0)) {
+        fprintf(stderr, "libxl_device_vtpm_add failed.\n");
+        return 1;
+    }
+    libxl_device_vtpm_dispose(&vtpm);
+    return 0;
+}
+
+int main_vtpmlist(int argc, char **argv)
+{
+    int opt;
+    libxl_device_vtpm *vtpms;
+    libxl_vtpminfo vtpminfo;
+    int nb, i;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vtpm-list", 1) {
+        /* No options */
+    }
+
+    /*      Idx  BE   UUID   Hdl  Sta  evch rref  BE-path */
+    printf("%-3s %-2s %-36s %-6s %-5s %-6s %-5s %-10s\n",
+           "Idx", "BE", "Uuid", "handle", "state", "evt-ch", "ring-ref", "BE-path");
+    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
+        uint32_t domid;
+        if (libxl_domain_qualifier_to_domid(ctx, *argv, &domid) < 0) {
+            fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
+            continue;
+        }
+        if (!(vtpms = libxl_device_vtpm_list(ctx, domid, &nb))) {
+            continue;
+        }
+        for (i = 0; i < nb; ++i) {
+           if(!libxl_device_vtpm_getinfo(ctx, domid, &vtpms[i], &vtpminfo)) {
+              /*      Idx  BE     UUID             Hdl Sta evch rref BE-path*/
+              printf("%-3d %-2d " LIBXL_UUID_FMT " %6d %5d %6d %8d %-30s\n",
+                    vtpminfo.devid, vtpminfo.backend_id,
+                    LIBXL_UUID_BYTES(vtpminfo.uuid),
+                    vtpminfo.devid, vtpminfo.state, vtpminfo.evtch,
+                    vtpminfo.rref, vtpminfo.backend);
+
+              libxl_vtpminfo_dispose(&vtpminfo);
+           }
+           libxl_device_vtpm_dispose(&vtpms[i]);
+        }
+        free(vtpms);
+    }
+    return 0;
+}
+
+int main_vtpmdetach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, rc=0;
+    libxl_device_vtpm vtpm;
+    libxl_uuid uuid;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vtpm-detach", 2) {
+        /* No options */
+    }
+
+    domid = xfind_domain(argv[optind]);
+
+    if ( libxl_uuid_from_string(&uuid, argv[optind+1])) {
+        if (libxl_devid_to_device_vtpm(ctx, domid, atoi(argv[optind+1]), &vtpm)) {
+            fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
+            return 1;
+        }
+    } else {
+        if (libxl_uuid_to_device_vtpm(ctx, domid, &uuid, &vtpm)) {
+            fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
+            return 1;
+        }
+    }
+    rc = libxl_device_vtpm_remove(ctx, domid, &vtpm, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_vtpm_remove failed.\n");
+    }
+    libxl_device_vtpm_dispose(&vtpm);
+    return rc;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 14/29] xl: split out block related code
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (12 preceding siblings ...)
  2017-02-24 16:12 ` [PATCH 13/29] xl: split out vtpm " Wei Liu
@ 2017-02-24 16:12 ` Wei Liu
  2017-02-27 15:58   ` Ian Jackson
  2017-02-24 16:13 ` [PATCH 15/29] xl: split out network " Wei Liu
                   ` (14 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:12 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   2 +-
 tools/xl/xl_block.c   | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/xl/xl_cmdimpl.c |  99 --------------------------------------
 3 files changed, 130 insertions(+), 100 deletions(-)
 create mode 100644 tools/xl/xl_block.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index b31ec052c1..331ae21293 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -17,7 +17,7 @@ CFLAGS_XL += -Wshadow
 
 XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
 XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
-XL_OBJS += xl_vtpm.o
+XL_OBJS += xl_vtpm.o xl_block.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_block.c b/tools/xl/xl_block.c
new file mode 100644
index 0000000000..b0d79931f9
--- /dev/null
+++ b/tools/xl/xl_block.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <stdlib.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+int main_blockattach(int argc, char **argv)
+{
+    int opt;
+    uint32_t fe_domid;
+    libxl_device_disk disk;
+    XLU_Config *config = 0;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "block-attach", 2) {
+        /* No options */
+    }
+
+    if (libxl_domain_qualifier_to_domid(ctx, argv[optind], &fe_domid) < 0) {
+        fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
+        return 1;
+    }
+    optind++;
+
+    parse_disk_config_multistring
+        (&config, argc-optind, (const char* const*)argv + optind, &disk);
+
+    if (dryrun_only) {
+        char *json = libxl_device_disk_to_json(ctx, &disk);
+        printf("disk: %s\n", json);
+        free(json);
+        if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
+        return 0;
+    }
+
+    if (libxl_device_disk_add(ctx, fe_domid, &disk, 0)) {
+        fprintf(stderr, "libxl_device_disk_add failed.\n");
+        return 1;
+    }
+    return 0;
+}
+
+int main_blocklist(int argc, char **argv)
+{
+    int opt;
+    int i, nb;
+    libxl_device_disk *disks;
+    libxl_diskinfo diskinfo;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "block-list", 1) {
+        /* No options */
+    }
+
+    printf("%-5s %-3s %-6s %-5s %-6s %-8s %-30s\n",
+           "Vdev", "BE", "handle", "state", "evt-ch", "ring-ref", "BE-path");
+    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
+        uint32_t domid;
+        if (libxl_domain_qualifier_to_domid(ctx, *argv, &domid) < 0) {
+            fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
+            continue;
+        }
+        disks = libxl_device_disk_list(ctx, domid, &nb);
+        if (!disks) {
+            continue;
+        }
+        for (i=0; i<nb; i++) {
+            if (!libxl_device_disk_getinfo(ctx, domid, &disks[i], &diskinfo)) {
+                /*      Vdev BE   hdl  st   evch rref BE-path*/
+                printf("%-5d %-3d %-6d %-5d %-6d %-8d %-30s\n",
+                       diskinfo.devid, diskinfo.backend_id, diskinfo.frontend_id,
+                       diskinfo.state, diskinfo.evtch, diskinfo.rref, diskinfo.backend);
+                libxl_diskinfo_dispose(&diskinfo);
+            }
+            libxl_device_disk_dispose(&disks[i]);
+        }
+        free(disks);
+    }
+    return 0;
+}
+
+int main_blockdetach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, rc = 0;
+    libxl_device_disk disk;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "block-detach", 2) {
+        /* No options */
+    }
+
+    domid = xfind_domain(argv[optind]);
+
+    if (libxl_vdev_to_device_disk(ctx, domid, argv[optind+1], &disk)) {
+        fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]);
+        return 1;
+    }
+    rc = libxl_device_disk_remove(ctx, domid, &disk, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_disk_remove failed.\n");
+        return 1;
+    }
+    libxl_device_disk_dispose(&disk);
+    return rc;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index aeb4fb362f..56524fe707 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -5176,105 +5176,6 @@ int main_channellist(int argc, char **argv)
     return 0;
 }
 
-int main_blockattach(int argc, char **argv)
-{
-    int opt;
-    uint32_t fe_domid;
-    libxl_device_disk disk;
-    XLU_Config *config = 0;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "block-attach", 2) {
-        /* No options */
-    }
-
-    if (libxl_domain_qualifier_to_domid(ctx, argv[optind], &fe_domid) < 0) {
-        fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
-        return 1;
-    }
-    optind++;
-
-    parse_disk_config_multistring
-        (&config, argc-optind, (const char* const*)argv + optind, &disk);
-
-    if (dryrun_only) {
-        char *json = libxl_device_disk_to_json(ctx, &disk);
-        printf("disk: %s\n", json);
-        free(json);
-        if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
-        return 0;
-    }
-
-    if (libxl_device_disk_add(ctx, fe_domid, &disk, 0)) {
-        fprintf(stderr, "libxl_device_disk_add failed.\n");
-        return 1;
-    }
-    return 0;
-}
-
-int main_blocklist(int argc, char **argv)
-{
-    int opt;
-    int i, nb;
-    libxl_device_disk *disks;
-    libxl_diskinfo diskinfo;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "block-list", 1) {
-        /* No options */
-    }
-
-    printf("%-5s %-3s %-6s %-5s %-6s %-8s %-30s\n",
-           "Vdev", "BE", "handle", "state", "evt-ch", "ring-ref", "BE-path");
-    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
-        uint32_t domid;
-        if (libxl_domain_qualifier_to_domid(ctx, *argv, &domid) < 0) {
-            fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
-            continue;
-        }
-        disks = libxl_device_disk_list(ctx, domid, &nb);
-        if (!disks) {
-            continue;
-        }
-        for (i=0; i<nb; i++) {
-            if (!libxl_device_disk_getinfo(ctx, domid, &disks[i], &diskinfo)) {
-                /*      Vdev BE   hdl  st   evch rref BE-path*/
-                printf("%-5d %-3d %-6d %-5d %-6d %-8d %-30s\n",
-                       diskinfo.devid, diskinfo.backend_id, diskinfo.frontend_id,
-                       diskinfo.state, diskinfo.evtch, diskinfo.rref, diskinfo.backend);
-                libxl_diskinfo_dispose(&diskinfo);
-            }
-            libxl_device_disk_dispose(&disks[i]);
-        }
-        free(disks);
-    }
-    return 0;
-}
-
-int main_blockdetach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt, rc = 0;
-    libxl_device_disk disk;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "block-detach", 2) {
-        /* No options */
-    }
-
-    domid = xfind_domain(argv[optind]);
-
-    if (libxl_vdev_to_device_disk(ctx, domid, argv[optind+1], &disk)) {
-        fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]);
-        return 1;
-    }
-    rc = libxl_device_disk_remove(ctx, domid, &disk, 0);
-    if (rc) {
-        fprintf(stderr, "libxl_device_disk_remove failed.\n");
-        return 1;
-    }
-    libxl_device_disk_dispose(&disk);
-    return rc;
-}
-
-
 static char *uptime_to_string(unsigned long uptime, int short_mode)
 {
     int sec, min, hour, day;
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 15/29] xl: split out network related code
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (13 preceding siblings ...)
  2017-02-24 16:12 ` [PATCH 14/29] xl: split out block " Wei Liu
@ 2017-02-24 16:13 ` Wei Liu
  2017-02-27 16:01   ` Ian Jackson
  2017-02-24 16:13 ` [PATCH 16/29] xl: split out usb " Wei Liu
                   ` (13 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:13 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   2 +-
 tools/xl/xl_cmdimpl.c | 140 ----------------------------------------
 tools/xl/xl_nic.c     | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 173 insertions(+), 141 deletions(-)
 create mode 100644 tools/xl/xl_nic.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index 331ae21293..c2f2ca38f4 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -17,7 +17,7 @@ CFLAGS_XL += -Wshadow
 
 XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
 XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
-XL_OBJS += xl_vtpm.o xl_block.o
+XL_OBJS += xl_vtpm.o xl_block.o xl_nic.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index 56524fe707..eab7865bef 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -364,31 +364,6 @@ out:
     return ret;
 }
 
-void set_default_nic_values(libxl_device_nic *nic);
-void set_default_nic_values(libxl_device_nic *nic)
-{
-
-    if (default_vifscript) {
-        free(nic->script);
-        nic->script = strdup(default_vifscript);
-    }
-
-    if (default_bridge) {
-        free(nic->bridge);
-        nic->bridge = strdup(default_bridge);
-    }
-
-    if (default_gatewaydev) {
-        free(nic->gatewaydev);
-        nic->gatewaydev = strdup(default_gatewaydev);
-    }
-
-    if (default_vifbackend) {
-        free(nic->backend_domname);
-        nic->backend_domname = strdup(default_vifbackend);
-    }
-}
-
 static void reload_domain_config(uint32_t domid,
                                  libxl_domain_config *d_config)
 {
@@ -5017,121 +4992,6 @@ int main_top(int argc, char **argv)
     return system("xentop");
 }
 
-int main_networkattach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    libxl_device_nic nic;
-    XLU_Config *config = 0;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "network-attach", 1) {
-        /* No options */
-    }
-
-    domid = xfind_domain(argv[optind]);
-
-    config= xlu_cfg_init(stderr, "command line");
-    if (!config) {
-        fprintf(stderr, "Failed to allocate for configuration\n");
-        return 1;
-    }
-
-    libxl_device_nic_init(&nic);
-    set_default_nic_values(&nic);
-
-    for (argv += optind+1, argc -= optind+1; argc > 0; ++argv, --argc) {
-        if (parse_nic_config(&nic, &config, *argv))
-            return 1;
-    }
-
-    if (dryrun_only) {
-        char *json = libxl_device_nic_to_json(ctx, &nic);
-        printf("vif: %s\n", json);
-        free(json);
-        libxl_device_nic_dispose(&nic);
-        if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
-        return 0;
-    }
-
-    if (libxl_device_nic_add(ctx, domid, &nic, 0)) {
-        fprintf(stderr, "libxl_device_nic_add failed.\n");
-        return 1;
-    }
-    libxl_device_nic_dispose(&nic);
-    xlu_cfg_destroy(config);
-    return 0;
-}
-
-int main_networklist(int argc, char **argv)
-{
-    int opt;
-    libxl_device_nic *nics;
-    libxl_nicinfo nicinfo;
-    int nb, i;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "network-list", 1) {
-        /* No options */
-    }
-
-    /*      Idx  BE   MAC   Hdl  Sta  evch txr/rxr  BE-path */
-    printf("%-3s %-2s %-17s %-6s %-5s %-6s %5s/%-5s %-30s\n",
-           "Idx", "BE", "Mac Addr.", "handle", "state", "evt-ch", "tx-", "rx-ring-ref", "BE-path");
-    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
-        uint32_t domid = xfind_domain(*argv);
-        nics = libxl_device_nic_list(ctx, domid, &nb);
-        if (!nics) {
-            continue;
-        }
-        for (i = 0; i < nb; ++i) {
-            if (!libxl_device_nic_getinfo(ctx, domid, &nics[i], &nicinfo)) {
-                /* Idx BE */
-                printf("%-3d %-2d ", nicinfo.devid, nicinfo.backend_id);
-                /* MAC */
-                printf(LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nics[i].mac));
-                /* Hdl  Sta  evch txr/rxr  BE-path */
-                printf("%6d %5d %6d %5d/%-11d %-30s\n",
-                       nicinfo.devid, nicinfo.state, nicinfo.evtch,
-                       nicinfo.rref_tx, nicinfo.rref_rx, nicinfo.backend);
-                libxl_nicinfo_dispose(&nicinfo);
-            }
-            libxl_device_nic_dispose(&nics[i]);
-        }
-        free(nics);
-    }
-    return 0;
-}
-
-int main_networkdetach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    libxl_device_nic nic;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "network-detach", 2) {
-        /* No options */
-    }
-
-    domid = xfind_domain(argv[optind]);
-
-    if (!strchr(argv[optind+1], ':')) {
-        if (libxl_devid_to_device_nic(ctx, domid, atoi(argv[optind+1]), &nic)) {
-            fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
-            return 1;
-        }
-    } else {
-        if (libxl_mac_to_device_nic(ctx, domid, argv[optind+1], &nic)) {
-            fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
-            return 1;
-        }
-    }
-    if (libxl_device_nic_remove(ctx, domid, &nic, 0)) {
-        fprintf(stderr, "libxl_device_nic_del failed.\n");
-        return 1;
-    }
-    libxl_device_nic_dispose(&nic);
-    return 0;
-}
-
 int main_channellist(int argc, char **argv)
 {
     int opt;
diff --git a/tools/xl/xl_nic.c b/tools/xl/xl_nic.c
new file mode 100644
index 0000000000..281a62c828
--- /dev/null
+++ b/tools/xl/xl_nic.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <stdlib.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+void set_default_nic_values(libxl_device_nic *nic);
+void set_default_nic_values(libxl_device_nic *nic)
+{
+
+    if (default_vifscript) {
+        free(nic->script);
+        nic->script = strdup(default_vifscript);
+    }
+
+    if (default_bridge) {
+        free(nic->bridge);
+        nic->bridge = strdup(default_bridge);
+    }
+
+    if (default_gatewaydev) {
+        free(nic->gatewaydev);
+        nic->gatewaydev = strdup(default_gatewaydev);
+    }
+
+    if (default_vifbackend) {
+        free(nic->backend_domname);
+        nic->backend_domname = strdup(default_vifbackend);
+    }
+}
+
+int main_networkattach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    libxl_device_nic nic;
+    XLU_Config *config = 0;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "network-attach", 1) {
+        /* No options */
+    }
+
+    domid = xfind_domain(argv[optind]);
+
+    config= xlu_cfg_init(stderr, "command line");
+    if (!config) {
+        fprintf(stderr, "Failed to allocate for configuration\n");
+        return 1;
+    }
+
+    libxl_device_nic_init(&nic);
+    set_default_nic_values(&nic);
+
+    for (argv += optind+1, argc -= optind+1; argc > 0; ++argv, --argc) {
+        if (parse_nic_config(&nic, &config, *argv))
+            return 1;
+    }
+
+    if (dryrun_only) {
+        char *json = libxl_device_nic_to_json(ctx, &nic);
+        printf("vif: %s\n", json);
+        free(json);
+        libxl_device_nic_dispose(&nic);
+        if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
+        return 0;
+    }
+
+    if (libxl_device_nic_add(ctx, domid, &nic, 0)) {
+        fprintf(stderr, "libxl_device_nic_add failed.\n");
+        return 1;
+    }
+    libxl_device_nic_dispose(&nic);
+    xlu_cfg_destroy(config);
+    return 0;
+}
+
+int main_networklist(int argc, char **argv)
+{
+    int opt;
+    libxl_device_nic *nics;
+    libxl_nicinfo nicinfo;
+    int nb, i;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "network-list", 1) {
+        /* No options */
+    }
+
+    /*      Idx  BE   MAC   Hdl  Sta  evch txr/rxr  BE-path */
+    printf("%-3s %-2s %-17s %-6s %-5s %-6s %5s/%-5s %-30s\n",
+           "Idx", "BE", "Mac Addr.", "handle", "state", "evt-ch", "tx-", "rx-ring-ref", "BE-path");
+    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
+        uint32_t domid = xfind_domain(*argv);
+        nics = libxl_device_nic_list(ctx, domid, &nb);
+        if (!nics) {
+            continue;
+        }
+        for (i = 0; i < nb; ++i) {
+            if (!libxl_device_nic_getinfo(ctx, domid, &nics[i], &nicinfo)) {
+                /* Idx BE */
+                printf("%-3d %-2d ", nicinfo.devid, nicinfo.backend_id);
+                /* MAC */
+                printf(LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nics[i].mac));
+                /* Hdl  Sta  evch txr/rxr  BE-path */
+                printf("%6d %5d %6d %5d/%-11d %-30s\n",
+                       nicinfo.devid, nicinfo.state, nicinfo.evtch,
+                       nicinfo.rref_tx, nicinfo.rref_rx, nicinfo.backend);
+                libxl_nicinfo_dispose(&nicinfo);
+            }
+            libxl_device_nic_dispose(&nics[i]);
+        }
+        free(nics);
+    }
+    return 0;
+}
+
+int main_networkdetach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    libxl_device_nic nic;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "network-detach", 2) {
+        /* No options */
+    }
+
+    domid = xfind_domain(argv[optind]);
+
+    if (!strchr(argv[optind+1], ':')) {
+        if (libxl_devid_to_device_nic(ctx, domid, atoi(argv[optind+1]), &nic)) {
+            fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
+            return 1;
+        }
+    } else {
+        if (libxl_mac_to_device_nic(ctx, domid, argv[optind+1], &nic)) {
+            fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
+            return 1;
+        }
+    }
+    if (libxl_device_nic_remove(ctx, domid, &nic, 0)) {
+        fprintf(stderr, "libxl_device_nic_del failed.\n");
+        return 1;
+    }
+    libxl_device_nic_dispose(&nic);
+    return 0;
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 16/29] xl: split out usb related code
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (14 preceding siblings ...)
  2017-02-24 16:13 ` [PATCH 15/29] xl: split out network " Wei Liu
@ 2017-02-24 16:13 ` Wei Liu
  2017-02-27 16:00   ` Ian Jackson
  2017-02-24 16:13 ` [PATCH 17/29] xl: split out scheduler " Wei Liu
                   ` (12 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:13 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   2 +-
 tools/xl/xl_cmdimpl.c | 190 ------------------------------------------
 tools/xl/xl_usb.c     | 222 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 223 insertions(+), 191 deletions(-)
 create mode 100644 tools/xl/xl_usb.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index c2f2ca38f4..45ddc255f5 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -17,7 +17,7 @@ CFLAGS_XL += -Wshadow
 
 XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
 XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
-XL_OBJS += xl_vtpm.o xl_block.o xl_nic.o
+XL_OBJS += xl_vtpm.o xl_block.o xl_nic.o xl_usb.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index eab7865bef..386f96b4cc 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -1293,196 +1293,6 @@ int main_cd_insert(int argc, char **argv)
     return EXIT_SUCCESS;
 }
 
-int main_usbctrl_attach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt, rc = 0;
-    libxl_device_usbctrl usbctrl;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "usbctrl-attach", 1) {
-        /* No options */
-    }
-
-    domid = xfind_domain(argv[optind++]);
-
-    libxl_device_usbctrl_init(&usbctrl);
-
-    for (argv += optind, argc -= optind; argc > 0; ++argv, --argc) {
-        if (parse_usbctrl_config(&usbctrl, *argv))
-            return 1;
-    }
-
-    rc = libxl_device_usbctrl_add(ctx, domid, &usbctrl, 0);
-    if (rc) {
-        fprintf(stderr, "libxl_device_usbctrl_add failed.\n");
-        rc = 1;
-    }
-
-    libxl_device_usbctrl_dispose(&usbctrl);
-    return rc;
-}
-
-int main_usbctrl_detach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt, devid, rc;
-    libxl_device_usbctrl usbctrl;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "usbctrl-detach", 2) {
-        /* No options */
-    }
-
-    domid = xfind_domain(argv[optind]);
-    devid = atoi(argv[optind+1]);
-
-    libxl_device_usbctrl_init(&usbctrl);
-    if (libxl_devid_to_device_usbctrl(ctx, domid, devid, &usbctrl)) {
-        fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
-        return 1;
-    }
-
-    rc = libxl_device_usbctrl_remove(ctx, domid, &usbctrl, 0);
-    if (rc) {
-        fprintf(stderr, "libxl_device_usbctrl_remove failed.\n");
-        rc = 1;
-    }
-
-    libxl_device_usbctrl_dispose(&usbctrl);
-    return rc;
-
-}
-
-int main_usbdev_attach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt, rc;
-    libxl_device_usbdev usbdev;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "usbdev-attach", 2) {
-        /* No options */
-    }
-
-    libxl_device_usbdev_init(&usbdev);
-
-    domid = xfind_domain(argv[optind++]);
-
-    for (argv += optind, argc -= optind; argc > 0; ++argv, --argc) {
-        if (parse_usbdev_config(&usbdev, *argv))
-            return 1;
-    }
-
-    rc = libxl_device_usbdev_add(ctx, domid, &usbdev, 0);
-    if (rc) {
-        fprintf(stderr, "libxl_device_usbdev_add failed.\n");
-        rc = 1;
-    }
-
-    libxl_device_usbdev_dispose(&usbdev);
-    return rc;
-}
-
-int main_usbdev_detach(int argc, char **argv)
-{
-    uint32_t domid;
-    int ctrl, port;
-    int opt, rc = 1;
-    libxl_device_usbdev usbdev;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "usbdev-detach", 3) {
-        /* No options */
-    }
-
-    domid = xfind_domain(argv[optind]);
-    ctrl = atoi(argv[optind+1]);
-    port = atoi(argv[optind+2]);
-
-    if (argc - optind > 3) {
-        fprintf(stderr, "Invalid arguments.\n");
-        return 1;
-    }
-
-    libxl_device_usbdev_init(&usbdev);
-    if (libxl_ctrlport_to_device_usbdev(ctx, domid, ctrl, port, &usbdev)) {
-        fprintf(stderr, "Unknown device at controller %d port %d.\n",
-                ctrl, port);
-        return 1;
-    }
-
-    rc = libxl_device_usbdev_remove(ctx, domid, &usbdev, 0);
-    if (rc) {
-        fprintf(stderr, "libxl_device_usbdev_remove failed.\n");
-        rc = 1;
-    }
-
-    libxl_device_usbdev_dispose(&usbdev);
-    return rc;
-}
-
-int main_usblist(int argc, char **argv)
-{
-    uint32_t domid;
-    libxl_device_usbctrl *usbctrls;
-    libxl_usbctrlinfo usbctrlinfo;
-    int numctrl, i, j, opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-list", 1) {
-        /* No options */
-    }
-
-    domid = xfind_domain(argv[optind++]);
-
-    if (argc > optind) {
-        fprintf(stderr, "Invalid arguments.\n");
-        exit(-1);
-    }
-
-    usbctrls = libxl_device_usbctrl_list(ctx, domid, &numctrl);
-    if (!usbctrls) {
-        return 0;
-    }
-
-    for (i = 0; i < numctrl; ++i) {
-        printf("%-6s %-12s %-3s %-5s %-7s %-5s\n",
-                "Devid", "Type", "BE", "state", "usb-ver", "ports");
-
-        libxl_usbctrlinfo_init(&usbctrlinfo);
-
-        if (!libxl_device_usbctrl_getinfo(ctx, domid,
-                                &usbctrls[i], &usbctrlinfo)) {
-            printf("%-6d %-12s %-3d %-5d %-7d %-5d\n",
-                    usbctrlinfo.devid,
-                    libxl_usbctrl_type_to_string(usbctrlinfo.type),
-                    usbctrlinfo.backend_id, usbctrlinfo.state,
-                    usbctrlinfo.version, usbctrlinfo.ports);
-
-            for (j = 1; j <= usbctrlinfo.ports; j++) {
-                libxl_device_usbdev usbdev;
-
-                libxl_device_usbdev_init(&usbdev);
-
-                printf("  Port %d:", j);
-
-                if (!libxl_ctrlport_to_device_usbdev(ctx, domid,
-                                                     usbctrlinfo.devid,
-                                                     j, &usbdev)) {
-                    printf(" Bus %03x Device %03x\n",
-                           usbdev.u.hostdev.hostbus,
-                           usbdev.u.hostdev.hostaddr);
-                } else {
-                    printf("\n");
-                }
-
-                libxl_device_usbdev_dispose(&usbdev);
-            }
-        }
-
-        libxl_usbctrlinfo_dispose(&usbctrlinfo);
-    }
-
-    libxl_device_usbctrl_list_free(usbctrls, numctrl);
-    return 0;
-}
-
 int main_console(int argc, char **argv)
 {
     uint32_t domid;
diff --git a/tools/xl/xl_usb.c b/tools/xl/xl_usb.c
new file mode 100644
index 0000000000..8c872b8e2e
--- /dev/null
+++ b/tools/xl/xl_usb.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <stdlib.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+int main_usbctrl_attach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, rc = 0;
+    libxl_device_usbctrl usbctrl;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usbctrl-attach", 1) {
+        /* No options */
+    }
+
+    domid = xfind_domain(argv[optind++]);
+
+    libxl_device_usbctrl_init(&usbctrl);
+
+    for (argv += optind, argc -= optind; argc > 0; ++argv, --argc) {
+        if (parse_usbctrl_config(&usbctrl, *argv))
+            return 1;
+    }
+
+    rc = libxl_device_usbctrl_add(ctx, domid, &usbctrl, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_usbctrl_add failed.\n");
+        rc = 1;
+    }
+
+    libxl_device_usbctrl_dispose(&usbctrl);
+    return rc;
+}
+
+int main_usbctrl_detach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, devid, rc;
+    libxl_device_usbctrl usbctrl;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usbctrl-detach", 2) {
+        /* No options */
+    }
+
+    domid = xfind_domain(argv[optind]);
+    devid = atoi(argv[optind+1]);
+
+    libxl_device_usbctrl_init(&usbctrl);
+    if (libxl_devid_to_device_usbctrl(ctx, domid, devid, &usbctrl)) {
+        fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
+        return 1;
+    }
+
+    rc = libxl_device_usbctrl_remove(ctx, domid, &usbctrl, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_usbctrl_remove failed.\n");
+        rc = 1;
+    }
+
+    libxl_device_usbctrl_dispose(&usbctrl);
+    return rc;
+
+}
+
+int main_usbdev_attach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, rc;
+    libxl_device_usbdev usbdev;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usbdev-attach", 2) {
+        /* No options */
+    }
+
+    libxl_device_usbdev_init(&usbdev);
+
+    domid = xfind_domain(argv[optind++]);
+
+    for (argv += optind, argc -= optind; argc > 0; ++argv, --argc) {
+        if (parse_usbdev_config(&usbdev, *argv))
+            return 1;
+    }
+
+    rc = libxl_device_usbdev_add(ctx, domid, &usbdev, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_usbdev_add failed.\n");
+        rc = 1;
+    }
+
+    libxl_device_usbdev_dispose(&usbdev);
+    return rc;
+}
+
+int main_usbdev_detach(int argc, char **argv)
+{
+    uint32_t domid;
+    int ctrl, port;
+    int opt, rc = 1;
+    libxl_device_usbdev usbdev;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usbdev-detach", 3) {
+        /* No options */
+    }
+
+    domid = xfind_domain(argv[optind]);
+    ctrl = atoi(argv[optind+1]);
+    port = atoi(argv[optind+2]);
+
+    if (argc - optind > 3) {
+        fprintf(stderr, "Invalid arguments.\n");
+        return 1;
+    }
+
+    libxl_device_usbdev_init(&usbdev);
+    if (libxl_ctrlport_to_device_usbdev(ctx, domid, ctrl, port, &usbdev)) {
+        fprintf(stderr, "Unknown device at controller %d port %d.\n",
+                ctrl, port);
+        return 1;
+    }
+
+    rc = libxl_device_usbdev_remove(ctx, domid, &usbdev, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_usbdev_remove failed.\n");
+        rc = 1;
+    }
+
+    libxl_device_usbdev_dispose(&usbdev);
+    return rc;
+}
+
+int main_usblist(int argc, char **argv)
+{
+    uint32_t domid;
+    libxl_device_usbctrl *usbctrls;
+    libxl_usbctrlinfo usbctrlinfo;
+    int numctrl, i, j, opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-list", 1) {
+        /* No options */
+    }
+
+    domid = xfind_domain(argv[optind++]);
+
+    if (argc > optind) {
+        fprintf(stderr, "Invalid arguments.\n");
+        exit(-1);
+    }
+
+    usbctrls = libxl_device_usbctrl_list(ctx, domid, &numctrl);
+    if (!usbctrls) {
+        return 0;
+    }
+
+    for (i = 0; i < numctrl; ++i) {
+        printf("%-6s %-12s %-3s %-5s %-7s %-5s\n",
+                "Devid", "Type", "BE", "state", "usb-ver", "ports");
+
+        libxl_usbctrlinfo_init(&usbctrlinfo);
+
+        if (!libxl_device_usbctrl_getinfo(ctx, domid,
+                                &usbctrls[i], &usbctrlinfo)) {
+            printf("%-6d %-12s %-3d %-5d %-7d %-5d\n",
+                    usbctrlinfo.devid,
+                    libxl_usbctrl_type_to_string(usbctrlinfo.type),
+                    usbctrlinfo.backend_id, usbctrlinfo.state,
+                    usbctrlinfo.version, usbctrlinfo.ports);
+
+            for (j = 1; j <= usbctrlinfo.ports; j++) {
+                libxl_device_usbdev usbdev;
+
+                libxl_device_usbdev_init(&usbdev);
+
+                printf("  Port %d:", j);
+
+                if (!libxl_ctrlport_to_device_usbdev(ctx, domid,
+                                                     usbctrlinfo.devid,
+                                                     j, &usbdev)) {
+                    printf(" Bus %03x Device %03x\n",
+                           usbdev.u.hostdev.hostbus,
+                           usbdev.u.hostdev.hostaddr);
+                } else {
+                    printf("\n");
+                }
+
+                libxl_device_usbdev_dispose(&usbdev);
+            }
+        }
+
+        libxl_usbctrlinfo_dispose(&usbctrlinfo);
+    }
+
+    libxl_device_usbctrl_list_free(usbctrls, numctrl);
+    return 0;
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 17/29] xl: split out scheduler related code
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (15 preceding siblings ...)
  2017-02-24 16:13 ` [PATCH 16/29] xl: split out usb " Wei Liu
@ 2017-02-24 16:13 ` Wei Liu
  2017-02-27 15:57   ` Ian Jackson
  2017-02-24 16:13 ` [PATCH 18/29] xl: split out pci " Wei Liu
                   ` (11 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:13 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   1 +
 tools/xl/xl_cmdimpl.c | 856 ------------------------------------------------
 tools/xl/xl_sched.c   | 888 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 889 insertions(+), 856 deletions(-)
 create mode 100644 tools/xl/xl_sched.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index 45ddc255f5..8aa294d5a0 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -18,6 +18,7 @@ CFLAGS_XL += -Wshadow
 XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
 XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
 XL_OBJS += xl_vtpm.o xl_block.o xl_nic.o xl_usb.o
+XL_OBJS += xl_sched.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index 386f96b4cc..7d6de3957e 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -3757,862 +3757,6 @@ int main_sharing(int argc, char **argv)
     return EXIT_SUCCESS;
 }
 
-static int sched_domain_get(libxl_scheduler sched, int domid,
-                            libxl_domain_sched_params *scinfo)
-{
-    if (libxl_domain_sched_params_get(ctx, domid, scinfo)) {
-        fprintf(stderr, "libxl_domain_sched_params_get failed.\n");
-        return 1;
-    }
-    if (scinfo->sched != sched) {
-        fprintf(stderr, "libxl_domain_sched_params_get returned %s not %s.\n",
-                libxl_scheduler_to_string(scinfo->sched),
-                libxl_scheduler_to_string(sched));
-        return 1;
-    }
-
-    return 0;
-}
-
-static int sched_domain_set(int domid, const libxl_domain_sched_params *scinfo)
-{
-    if (libxl_domain_sched_params_set(ctx, domid, scinfo)) {
-        fprintf(stderr, "libxl_domain_sched_params_set failed.\n");
-        return 1;
-    }
-
-    return 0;
-}
-
-static int sched_vcpu_get(libxl_scheduler sched, int domid,
-                          libxl_vcpu_sched_params *scinfo)
-{
-    int rc;
-
-    rc = libxl_vcpu_sched_params_get(ctx, domid, scinfo);
-    if (rc) {
-        fprintf(stderr, "libxl_vcpu_sched_params_get failed.\n");
-        exit(EXIT_FAILURE);
-    }
-    if (scinfo->sched != sched) {
-        fprintf(stderr, "libxl_vcpu_sched_params_get returned %s not %s.\n",
-                libxl_scheduler_to_string(scinfo->sched),
-                libxl_scheduler_to_string(sched));
-        return 1;
-    }
-
-    return 0;
-}
-
-static int sched_vcpu_get_all(libxl_scheduler sched, int domid,
-                              libxl_vcpu_sched_params *scinfo)
-{
-    int rc;
-
-    rc = libxl_vcpu_sched_params_get_all(ctx, domid, scinfo);
-    if (rc) {
-        fprintf(stderr, "libxl_vcpu_sched_params_get_all failed.\n");
-        exit(EXIT_FAILURE);
-    }
-    if (scinfo->sched != sched) {
-        fprintf(stderr, "libxl_vcpu_sched_params_get_all returned %s not %s.\n",
-                libxl_scheduler_to_string(scinfo->sched),
-                libxl_scheduler_to_string(sched));
-        return 1;
-    }
-
-    return 0;
-}
-
-static int sched_vcpu_set(int domid, const libxl_vcpu_sched_params *scinfo)
-{
-    int rc;
-
-    rc = libxl_vcpu_sched_params_set(ctx, domid, scinfo);
-    if (rc) {
-        fprintf(stderr, "libxl_vcpu_sched_params_set failed.\n");
-        exit(EXIT_FAILURE);
-    }
-
-    return 0;
-}
-
-static int sched_vcpu_set_all(int domid, const libxl_vcpu_sched_params *scinfo)
-{
-    int rc;
-
-    rc = libxl_vcpu_sched_params_set_all(ctx, domid, scinfo);
-    if (rc) {
-        fprintf(stderr, "libxl_vcpu_sched_params_set_all failed.\n");
-        exit(EXIT_FAILURE);
-    }
-
-    return 0;
-}
-
-static int sched_credit_params_set(int poolid, libxl_sched_credit_params *scinfo)
-{
-    if (libxl_sched_credit_params_set(ctx, poolid, scinfo)) {
-        fprintf(stderr, "libxl_sched_credit_params_set failed.\n");
-        return 1;
-    }
-
-    return 0;
-}
-
-static int sched_credit_params_get(int poolid, libxl_sched_credit_params *scinfo)
-{
-    if (libxl_sched_credit_params_get(ctx, poolid, scinfo)) {
-        fprintf(stderr, "libxl_sched_credit_params_get failed.\n");
-        return 1;
-    }
-
-    return 0;
-}
-
-static int sched_credit_domain_output(int domid)
-{
-    char *domname;
-    libxl_domain_sched_params scinfo;
-
-    if (domid < 0) {
-        printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
-        return 0;
-    }
-
-    libxl_domain_sched_params_init(&scinfo);
-    if (sched_domain_get(LIBXL_SCHEDULER_CREDIT, domid, &scinfo)) {
-        libxl_domain_sched_params_dispose(&scinfo);
-        return 1;
-    }
-    domname = libxl_domid_to_name(ctx, domid);
-    printf("%-33s %4d %6d %4d\n",
-        domname,
-        domid,
-        scinfo.weight,
-        scinfo.cap);
-    free(domname);
-    libxl_domain_sched_params_dispose(&scinfo);
-    return 0;
-}
-
-static int sched_credit_pool_output(uint32_t poolid)
-{
-    libxl_sched_credit_params scparam;
-    char *poolname;
-
-    poolname = libxl_cpupoolid_to_name(ctx, poolid);
-    if (sched_credit_params_get(poolid, &scparam)) {
-        printf("Cpupool %s: [sched params unavailable]\n",
-               poolname);
-    } else {
-        printf("Cpupool %s: tslice=%dms ratelimit=%dus\n",
-               poolname,
-               scparam.tslice_ms,
-               scparam.ratelimit_us);
-    }
-    free(poolname);
-    return 0;
-}
-
-static int sched_credit2_params_set(int poolid,
-                                    libxl_sched_credit2_params *scinfo)
-{
-    if (libxl_sched_credit2_params_set(ctx, poolid, scinfo)) {
-        fprintf(stderr, "libxl_sched_credit2_params_set failed.\n");
-        return 1;
-    }
-
-    return 0;
-}
-
-static int sched_credit2_params_get(int poolid,
-                                    libxl_sched_credit2_params *scinfo)
-{
-    if (libxl_sched_credit2_params_get(ctx, poolid, scinfo)) {
-        fprintf(stderr, "libxl_sched_credit2_params_get failed.\n");
-        return 1;
-    }
-
-    return 0;
-}
-
-static int sched_credit2_domain_output(int domid)
-{
-    char *domname;
-    libxl_domain_sched_params scinfo;
-
-    if (domid < 0) {
-        printf("%-33s %4s %6s\n", "Name", "ID", "Weight");
-        return 0;
-    }
-
-    libxl_domain_sched_params_init(&scinfo);
-    if (sched_domain_get(LIBXL_SCHEDULER_CREDIT2, domid, &scinfo)) {
-        libxl_domain_sched_params_dispose(&scinfo);
-        return 1;
-    }
-    domname = libxl_domid_to_name(ctx, domid);
-    printf("%-33s %4d %6d\n",
-        domname,
-        domid,
-        scinfo.weight);
-    free(domname);
-    libxl_domain_sched_params_dispose(&scinfo);
-    return 0;
-}
-
-static int sched_credit2_pool_output(uint32_t poolid)
-{
-    libxl_sched_credit2_params scparam;
-    char *poolname = libxl_cpupoolid_to_name(ctx, poolid);
-
-    if (sched_credit2_params_get(poolid, &scparam))
-        printf("Cpupool %s: [sched params unavailable]\n", poolname);
-    else
-        printf("Cpupool %s: ratelimit=%dus\n",
-               poolname, scparam.ratelimit_us);
-
-    free(poolname);
-
-    return 0;
-}
-
-static int sched_rtds_domain_output(
-    int domid)
-{
-    char *domname;
-    libxl_domain_sched_params scinfo;
-
-    if (domid < 0) {
-        printf("%-33s %4s %9s %9s\n", "Name", "ID", "Period", "Budget");
-        return 0;
-    }
-
-    libxl_domain_sched_params_init(&scinfo);
-    if (sched_domain_get(LIBXL_SCHEDULER_RTDS, domid, &scinfo)) {
-        libxl_domain_sched_params_dispose(&scinfo);
-        return 1;
-    }
-
-    domname = libxl_domid_to_name(ctx, domid);
-    printf("%-33s %4d %9d %9d\n",
-        domname,
-        domid,
-        scinfo.period,
-        scinfo.budget);
-    free(domname);
-    libxl_domain_sched_params_dispose(&scinfo);
-    return 0;
-}
-
-static int sched_rtds_vcpu_output(int domid, libxl_vcpu_sched_params *scinfo)
-{
-    char *domname;
-    int rc = 0;
-    int i;
-
-    if (domid < 0) {
-        printf("%-33s %4s %4s %9s %9s\n", "Name", "ID",
-               "VCPU", "Period", "Budget");
-        return 0;
-    }
-
-    rc = sched_vcpu_get(LIBXL_SCHEDULER_RTDS, domid, scinfo);
-    if (rc)
-        return 1;
-
-    domname = libxl_domid_to_name(ctx, domid);
-    for ( i = 0; i < scinfo->num_vcpus; i++ ) {
-        printf("%-33s %4d %4d %9"PRIu32" %9"PRIu32"\n",
-               domname,
-               domid,
-               scinfo->vcpus[i].vcpuid,
-               scinfo->vcpus[i].period,
-               scinfo->vcpus[i].budget);
-    }
-    free(domname);
-    return 0;
-}
-
-static int sched_rtds_vcpu_output_all(int domid,
-                                      libxl_vcpu_sched_params *scinfo)
-{
-    char *domname;
-    int rc = 0;
-    int i;
-
-    if (domid < 0) {
-        printf("%-33s %4s %4s %9s %9s\n", "Name", "ID",
-               "VCPU", "Period", "Budget");
-        return 0;
-    }
-
-    scinfo->num_vcpus = 0;
-    rc = sched_vcpu_get_all(LIBXL_SCHEDULER_RTDS, domid, scinfo);
-    if (rc)
-        return 1;
-
-    domname = libxl_domid_to_name(ctx, domid);
-    for ( i = 0; i < scinfo->num_vcpus; i++ ) {
-        printf("%-33s %4d %4d %9"PRIu32" %9"PRIu32"\n",
-               domname,
-               domid,
-               scinfo->vcpus[i].vcpuid,
-               scinfo->vcpus[i].period,
-               scinfo->vcpus[i].budget);
-    }
-    free(domname);
-    return 0;
-}
-
-static int sched_rtds_pool_output(uint32_t poolid)
-{
-    char *poolname;
-
-    poolname = libxl_cpupoolid_to_name(ctx, poolid);
-    printf("Cpupool %s: sched=RTDS\n", poolname);
-
-    free(poolname);
-    return 0;
-}
-
-static int sched_domain_output(libxl_scheduler sched, int (*output)(int),
-                               int (*pooloutput)(uint32_t), const char *cpupool)
-{
-    libxl_dominfo *info;
-    libxl_cpupoolinfo *poolinfo = NULL;
-    uint32_t poolid;
-    int nb_domain, n_pools = 0, i, p;
-    int rc = 0;
-
-    if (cpupool) {
-        if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool, &poolid, NULL) ||
-            !libxl_cpupoolid_is_valid(ctx, poolid)) {
-            fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
-            return 1;
-        }
-    }
-
-    info = libxl_list_domain(ctx, &nb_domain);
-    if (!info) {
-        fprintf(stderr, "libxl_list_domain failed.\n");
-        return 1;
-    }
-    poolinfo = libxl_list_cpupool(ctx, &n_pools);
-    if (!poolinfo) {
-        fprintf(stderr, "error getting cpupool info\n");
-        libxl_dominfo_list_free(info, nb_domain);
-        return 1;
-    }
-
-    for (p = 0; !rc && (p < n_pools); p++) {
-        if ((poolinfo[p].sched != sched) ||
-            (cpupool && (poolid != poolinfo[p].poolid)))
-            continue;
-
-        pooloutput(poolinfo[p].poolid);
-
-        output(-1);
-        for (i = 0; i < nb_domain; i++) {
-            if (info[i].cpupool != poolinfo[p].poolid)
-                continue;
-            rc = output(info[i].domid);
-            if (rc)
-                break;
-        }
-    }
-
-    libxl_cpupoolinfo_list_free(poolinfo, n_pools);
-    libxl_dominfo_list_free(info, nb_domain);
-    return 0;
-}
-
-static int sched_vcpu_output(libxl_scheduler sched,
-                             int (*output)(int, libxl_vcpu_sched_params *),
-                             int (*pooloutput)(uint32_t), const char *cpupool)
-{
-    libxl_dominfo *info;
-    libxl_cpupoolinfo *poolinfo = NULL;
-    uint32_t poolid;
-    int nb_domain, n_pools = 0, i, p;
-    int rc = 0;
-
-    if (cpupool) {
-        if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool, &poolid, NULL)
-            || !libxl_cpupoolid_is_valid(ctx, poolid)) {
-            fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
-            return 1;
-        }
-    }
-
-    info = libxl_list_domain(ctx, &nb_domain);
-    if (!info) {
-        fprintf(stderr, "libxl_list_domain failed.\n");
-        return 1;
-    }
-    poolinfo = libxl_list_cpupool(ctx, &n_pools);
-    if (!poolinfo) {
-        fprintf(stderr, "error getting cpupool info\n");
-        libxl_dominfo_list_free(info, nb_domain);
-        return 1;
-    }
-
-    for (p = 0; !rc && (p < n_pools); p++) {
-        if ((poolinfo[p].sched != sched) ||
-            (cpupool && (poolid != poolinfo[p].poolid)))
-            continue;
-
-        pooloutput(poolinfo[p].poolid);
-
-        output(-1, NULL);
-        for (i = 0; i < nb_domain; i++) {
-            libxl_vcpu_sched_params scinfo;
-            if (info[i].cpupool != poolinfo[p].poolid)
-                continue;
-            libxl_vcpu_sched_params_init(&scinfo);
-            rc = output(info[i].domid, &scinfo);
-            libxl_vcpu_sched_params_dispose(&scinfo);
-            if (rc)
-                break;
-        }
-    }
-
-    libxl_cpupoolinfo_list_free(poolinfo, n_pools);
-    libxl_dominfo_list_free(info, nb_domain);
-    return 0;
-}
-
-/*
- * <nothing>             : List all domain params and sched params from all pools
- * -d [domid]            : List domain params for domain
- * -d [domid] [params]   : Set domain params for domain
- * -p [pool]             : list all domains and sched params for pool
- * -s                    : List sched params for poolid 0
- * -s [params]           : Set sched params for poolid 0
- * -p [pool] -s          : List sched params for pool
- * -p [pool] -s [params] : Set sched params for pool
- * -p [pool] -d...       : Illegal
- */
-int main_sched_credit(int argc, char **argv)
-{
-    const char *dom = NULL;
-    const char *cpupool = NULL;
-    int weight = 256, cap = 0;
-    int tslice = 0, ratelimit = 0;
-    bool opt_w = false, opt_c = false;
-    bool opt_t = false, opt_r = false;
-    bool opt_s = false;
-    int opt, rc;
-    static struct option opts[] = {
-        {"domain", 1, 0, 'd'},
-        {"weight", 1, 0, 'w'},
-        {"cap", 1, 0, 'c'},
-        {"schedparam", 0, 0, 's'},
-        {"tslice_ms", 1, 0, 't'},
-        {"ratelimit_us", 1, 0, 'r'},
-        {"cpupool", 1, 0, 'p'},
-        COMMON_LONG_OPTS
-    };
-
-    SWITCH_FOREACH_OPT(opt, "d:w:c:p:t:r:s", opts, "sched-credit", 0) {
-    case 'd':
-        dom = optarg;
-        break;
-    case 'w':
-        weight = strtol(optarg, NULL, 10);
-        opt_w = true;
-        break;
-    case 'c':
-        cap = strtol(optarg, NULL, 10);
-        opt_c = true;
-        break;
-    case 't':
-        tslice = strtol(optarg, NULL, 10);
-        opt_t = true;
-        break;
-    case 'r':
-        ratelimit = strtol(optarg, NULL, 10);
-        opt_r = true;
-        break;
-    case 's':
-        opt_s = true;
-        break;
-    case 'p':
-        cpupool = optarg;
-        break;
-    }
-
-    if ((cpupool || opt_s) && (dom || opt_w || opt_c)) {
-        fprintf(stderr, "Specifying a cpupool or schedparam is not "
-                "allowed with domain options.\n");
-        return EXIT_FAILURE;
-    }
-    if (!dom && (opt_w || opt_c)) {
-        fprintf(stderr, "Must specify a domain.\n");
-        return EXIT_FAILURE;
-    }
-    if (!opt_s && (opt_t || opt_r)) {
-        fprintf(stderr, "Must specify schedparam to set schedule "
-                "parameter values.\n");
-        return EXIT_FAILURE;
-    }
-
-    if (opt_s) {
-        libxl_sched_credit_params scparam;
-        uint32_t poolid = 0;
-
-        if (cpupool) {
-            if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool,
-                                                     &poolid, NULL) ||
-                !libxl_cpupoolid_is_valid(ctx, poolid)) {
-                fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
-                return EXIT_FAILURE;
-            }
-        }
-
-        if (!opt_t && !opt_r) { /* Output scheduling parameters */
-            if (sched_credit_pool_output(poolid))
-                return EXIT_FAILURE;
-        } else { /* Set scheduling parameters*/
-            if (sched_credit_params_get(poolid, &scparam))
-                return EXIT_FAILURE;
-
-            if (opt_t)
-                scparam.tslice_ms = tslice;
-
-            if (opt_r)
-                scparam.ratelimit_us = ratelimit;
-
-            if (sched_credit_params_set(poolid, &scparam))
-                return EXIT_FAILURE;
-        }
-    } else if (!dom) { /* list all domain's credit scheduler info */
-        if (sched_domain_output(LIBXL_SCHEDULER_CREDIT,
-                                sched_credit_domain_output,
-                                sched_credit_pool_output,
-                                cpupool))
-            return EXIT_FAILURE;
-    } else {
-        uint32_t domid = xfind_domain(dom);
-
-        if (!opt_w && !opt_c) { /* output credit scheduler info */
-            sched_credit_domain_output(-1);
-            if (sched_credit_domain_output(domid))
-                return EXIT_FAILURE;
-        } else { /* set credit scheduler paramaters */
-            libxl_domain_sched_params scinfo;
-            libxl_domain_sched_params_init(&scinfo);
-            scinfo.sched = LIBXL_SCHEDULER_CREDIT;
-            if (opt_w)
-                scinfo.weight = weight;
-            if (opt_c)
-                scinfo.cap = cap;
-            rc = sched_domain_set(domid, &scinfo);
-            libxl_domain_sched_params_dispose(&scinfo);
-            if (rc)
-                return EXIT_FAILURE;
-        }
-    }
-
-    return EXIT_SUCCESS;
-}
-
-int main_sched_credit2(int argc, char **argv)
-{
-    const char *dom = NULL;
-    const char *cpupool = NULL;
-    int ratelimit = 0;
-    int weight = 256;
-    bool opt_s = false;
-    bool opt_r = false;
-    bool opt_w = false;
-    int opt, rc;
-    static struct option opts[] = {
-        {"domain", 1, 0, 'd'},
-        {"weight", 1, 0, 'w'},
-        {"schedparam", 0, 0, 's'},
-        {"ratelimit_us", 1, 0, 'r'},
-        {"cpupool", 1, 0, 'p'},
-        COMMON_LONG_OPTS
-    };
-
-    SWITCH_FOREACH_OPT(opt, "d:w:p:r:s", opts, "sched-credit2", 0) {
-    case 'd':
-        dom = optarg;
-        break;
-    case 'w':
-        weight = strtol(optarg, NULL, 10);
-        opt_w = true;
-        break;
-    case 's':
-        opt_s = true;
-        break;
-    case 'r':
-        ratelimit = strtol(optarg, NULL, 10);
-        opt_r = true;
-        break;
-    case 'p':
-        cpupool = optarg;
-        break;
-    }
-
-    if (cpupool && (dom || opt_w)) {
-        fprintf(stderr, "Specifying a cpupool is not allowed with other "
-                "options.\n");
-        return EXIT_FAILURE;
-    }
-    if (!dom && opt_w) {
-        fprintf(stderr, "Must specify a domain.\n");
-        return EXIT_FAILURE;
-    }
-
-    if (opt_s) {
-        libxl_sched_credit2_params scparam;
-        uint32_t poolid = 0;
-
-        if (cpupool) {
-            if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool,
-                                                     &poolid, NULL) ||
-                !libxl_cpupoolid_is_valid(ctx, poolid)) {
-                fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
-                return EXIT_FAILURE;
-            }
-        }
-
-        if (!opt_r) { /* Output scheduling parameters */
-            if (sched_credit2_pool_output(poolid))
-                return EXIT_FAILURE;
-        } else {      /* Set scheduling parameters (so far, just ratelimit) */
-            scparam.ratelimit_us = ratelimit;
-            if (sched_credit2_params_set(poolid, &scparam))
-                return EXIT_FAILURE;
-        }
-    } else if (!dom) { /* list all domain's credit scheduler info */
-        if (sched_domain_output(LIBXL_SCHEDULER_CREDIT2,
-                                sched_credit2_domain_output,
-                                sched_credit2_pool_output,
-                                cpupool))
-            return EXIT_FAILURE;
-    } else {
-        uint32_t domid = xfind_domain(dom);
-
-        if (!opt_w) { /* output credit2 scheduler info */
-            sched_credit2_domain_output(-1);
-            if (sched_credit2_domain_output(domid))
-                return EXIT_FAILURE;
-        } else { /* set credit2 scheduler paramaters */
-            libxl_domain_sched_params scinfo;
-            libxl_domain_sched_params_init(&scinfo);
-            scinfo.sched = LIBXL_SCHEDULER_CREDIT2;
-            if (opt_w)
-                scinfo.weight = weight;
-            rc = sched_domain_set(domid, &scinfo);
-            libxl_domain_sched_params_dispose(&scinfo);
-            if (rc)
-                return EXIT_FAILURE;
-        }
-    }
-
-    return EXIT_SUCCESS;
-}
-
-/*
- * <nothing>            : List all domain paramters and sched params
- * -d [domid]           : List default domain params for domain
- * -d [domid] [params]  : Set domain params for domain
- * -d [domid] -v [vcpuid 1] -v [vcpuid 2] ...  :
- * List per-VCPU params for domain
- * -d [domid] -v all  : List all per-VCPU params for domain
- * -v all  : List all per-VCPU params for all domains
- * -d [domid] -v [vcpuid 1] [params] -v [vcpuid 2] [params] ...  :
- * Set per-VCPU params for domain
- * -d [domid] -v all [params]  : Set all per-VCPU params for domain
- */
-int main_sched_rtds(int argc, char **argv)
-{
-    const char *dom = NULL;
-    const char *cpupool = NULL;
-    int *vcpus = (int *)xmalloc(sizeof(int)); /* IDs of VCPUs that change */
-    int *periods = (int *)xmalloc(sizeof(int)); /* period is in microsecond */
-    int *budgets = (int *)xmalloc(sizeof(int)); /* budget is in microsecond */
-    int v_size = 1; /* size of vcpus array */
-    int p_size = 1; /* size of periods array */
-    int b_size = 1; /* size of budgets array */
-    int v_index = 0; /* index in vcpus array */
-    int p_index =0; /* index in periods array */
-    int b_index =0; /* index for in budgets array */
-    bool opt_p = false;
-    bool opt_b = false;
-    bool opt_v = false;
-    bool opt_all = false; /* output per-dom parameters */
-    int opt, i, rc, r;
-    static struct option opts[] = {
-        {"domain", 1, 0, 'd'},
-        {"period", 1, 0, 'p'},
-        {"budget", 1, 0, 'b'},
-        {"vcpuid",1, 0, 'v'},
-        {"cpupool", 1, 0, 'c'},
-        COMMON_LONG_OPTS
-    };
-
-    SWITCH_FOREACH_OPT(opt, "d:p:b:v:c", opts, "sched-rtds", 0) {
-    case 'd':
-        dom = optarg;
-        break;
-    case 'p':
-        if (p_index >= p_size) {
-            /*
-             * periods array is full
-             * double the array size for new elements
-             */
-            p_size *= 2;
-            periods = xrealloc(periods, p_size);
-        }
-        periods[p_index++] = strtol(optarg, NULL, 10);
-        opt_p = 1;
-        break;
-    case 'b':
-        if (b_index >= b_size) { /* budgets array is full */
-            b_size *= 2;
-            budgets = xrealloc(budgets, b_size);
-        }
-        budgets[b_index++] = strtol(optarg, NULL, 10);
-        opt_b = 1;
-        break;
-    case 'v':
-        if (!strcmp(optarg, "all")) { /* get or set all vcpus of a domain */
-            opt_all = 1;
-            break;
-        }
-        if (v_index >= v_size) { /* vcpus array is full */
-            v_size *= 2;
-            vcpus = xrealloc(vcpus, v_size);
-        }
-        vcpus[v_index++] = strtol(optarg, NULL, 10);
-        opt_v = 1;
-        break;
-    case 'c':
-        cpupool = optarg;
-        break;
-    }
-
-    if (cpupool && (dom || opt_p || opt_b || opt_v || opt_all)) {
-        fprintf(stderr, "Specifying a cpupool is not allowed with "
-                "other options.\n");
-        r = EXIT_FAILURE;
-        goto out;
-    }
-    if (!dom && (opt_p || opt_b || opt_v)) {
-        fprintf(stderr, "Missing parameters.\n");
-        r = EXIT_FAILURE;
-        goto out;
-    }
-    if (dom && !opt_v && !opt_all && (opt_p || opt_b)) {
-        fprintf(stderr, "Must specify VCPU.\n");
-        r = EXIT_FAILURE;
-        goto out;
-    }
-    if (opt_v && opt_all) {
-        fprintf(stderr, "Incorrect VCPU IDs.\n");
-        r = EXIT_FAILURE;
-        goto out;
-    }
-    if (((v_index > b_index) && opt_b) || ((v_index > p_index) && opt_p)
-        || p_index != b_index) {
-        fprintf(stderr, "Incorrect number of period and budget\n");
-        r = EXIT_FAILURE;
-        goto out;
-    }
-
-    if ((!dom) && opt_all) {
-        /* get all domain's per-vcpu rtds scheduler parameters */
-        rc = -sched_vcpu_output(LIBXL_SCHEDULER_RTDS,
-                                sched_rtds_vcpu_output_all,
-                                sched_rtds_pool_output,
-                                cpupool);
-        if (rc) {
-            r = EXIT_FAILURE;
-            goto out;
-        }
-    } else if (!dom && !opt_all) {
-        /* list all domain's default scheduling parameters */
-        rc = -sched_domain_output(LIBXL_SCHEDULER_RTDS,
-                                  sched_rtds_domain_output,
-                                  sched_rtds_pool_output,
-                                  cpupool);
-        if (rc) {
-            r = EXIT_FAILURE;
-            goto out;
-        }
-    } else {
-        uint32_t domid = xfind_domain(dom);
-        if (!opt_v && !opt_all) { /* output default scheduling parameters */
-            sched_rtds_domain_output(-1);
-            rc = -sched_rtds_domain_output(domid);
-            if (rc) {
-                r = EXIT_FAILURE;
-                goto out;
-            }
-        } else if (!opt_p && !opt_b) {
-            /* get per-vcpu rtds scheduling parameters */
-            libxl_vcpu_sched_params scinfo;
-            libxl_vcpu_sched_params_init(&scinfo);
-            sched_rtds_vcpu_output(-1, &scinfo);
-            scinfo.num_vcpus = v_index;
-            if (v_index > 0) {
-                scinfo.vcpus = (libxl_sched_params *)
-                               xmalloc(sizeof(libxl_sched_params) * (v_index));
-                for (i = 0; i < v_index; i++)
-                    scinfo.vcpus[i].vcpuid = vcpus[i];
-                rc = -sched_rtds_vcpu_output(domid, &scinfo);
-            } else /* get params for all vcpus */
-                rc = -sched_rtds_vcpu_output_all(domid, &scinfo);
-            libxl_vcpu_sched_params_dispose(&scinfo);
-            if (rc) {
-                r = EXIT_FAILURE;
-                goto out;
-            }
-    } else if (opt_v || opt_all) {
-            /* set per-vcpu rtds scheduling parameters */
-            libxl_vcpu_sched_params scinfo;
-            libxl_vcpu_sched_params_init(&scinfo);
-            scinfo.sched = LIBXL_SCHEDULER_RTDS;
-            if (v_index > 0) {
-                scinfo.num_vcpus = v_index;
-                scinfo.vcpus = (libxl_sched_params *)
-                               xmalloc(sizeof(libxl_sched_params) * (v_index));
-                for (i = 0; i < v_index; i++) {
-                    scinfo.vcpus[i].vcpuid = vcpus[i];
-                    scinfo.vcpus[i].period = periods[i];
-                    scinfo.vcpus[i].budget = budgets[i];
-                }
-                rc = sched_vcpu_set(domid, &scinfo);
-            } else { /* set params for all vcpus */
-                scinfo.num_vcpus = 1;
-                scinfo.vcpus = (libxl_sched_params *)
-                               xmalloc(sizeof(libxl_sched_params));
-                scinfo.vcpus[0].period = periods[0];
-                scinfo.vcpus[0].budget = budgets[0];
-                rc = sched_vcpu_set_all(domid, &scinfo);
-            }
-
-            libxl_vcpu_sched_params_dispose(&scinfo);
-            if (rc) {
-                r = EXIT_FAILURE;
-                goto out;
-            }
-        }
-    }
-
-    r = EXIT_SUCCESS;
-out:
-    free(vcpus);
-    free(periods);
-    free(budgets);
-    return r;
-}
-
 int main_domid(int argc, char **argv)
 {
     uint32_t domid;
diff --git a/tools/xl/xl_sched.c b/tools/xl/xl_sched.c
new file mode 100644
index 0000000000..50b254da81
--- /dev/null
+++ b/tools/xl/xl_sched.c
@@ -0,0 +1,888 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <inttypes.h>
+#include <stdlib.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+static int sched_domain_get(libxl_scheduler sched, int domid,
+                            libxl_domain_sched_params *scinfo)
+{
+    if (libxl_domain_sched_params_get(ctx, domid, scinfo)) {
+        fprintf(stderr, "libxl_domain_sched_params_get failed.\n");
+        return 1;
+    }
+    if (scinfo->sched != sched) {
+        fprintf(stderr, "libxl_domain_sched_params_get returned %s not %s.\n",
+                libxl_scheduler_to_string(scinfo->sched),
+                libxl_scheduler_to_string(sched));
+        return 1;
+    }
+
+    return 0;
+}
+
+static int sched_domain_set(int domid, const libxl_domain_sched_params *scinfo)
+{
+    if (libxl_domain_sched_params_set(ctx, domid, scinfo)) {
+        fprintf(stderr, "libxl_domain_sched_params_set failed.\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+static int sched_vcpu_get(libxl_scheduler sched, int domid,
+                          libxl_vcpu_sched_params *scinfo)
+{
+    int rc;
+
+    rc = libxl_vcpu_sched_params_get(ctx, domid, scinfo);
+    if (rc) {
+        fprintf(stderr, "libxl_vcpu_sched_params_get failed.\n");
+        exit(EXIT_FAILURE);
+    }
+    if (scinfo->sched != sched) {
+        fprintf(stderr, "libxl_vcpu_sched_params_get returned %s not %s.\n",
+                libxl_scheduler_to_string(scinfo->sched),
+                libxl_scheduler_to_string(sched));
+        return 1;
+    }
+
+    return 0;
+}
+
+static int sched_vcpu_get_all(libxl_scheduler sched, int domid,
+                              libxl_vcpu_sched_params *scinfo)
+{
+    int rc;
+
+    rc = libxl_vcpu_sched_params_get_all(ctx, domid, scinfo);
+    if (rc) {
+        fprintf(stderr, "libxl_vcpu_sched_params_get_all failed.\n");
+        exit(EXIT_FAILURE);
+    }
+    if (scinfo->sched != sched) {
+        fprintf(stderr, "libxl_vcpu_sched_params_get_all returned %s not %s.\n",
+                libxl_scheduler_to_string(scinfo->sched),
+                libxl_scheduler_to_string(sched));
+        return 1;
+    }
+
+    return 0;
+}
+
+static int sched_vcpu_set(int domid, const libxl_vcpu_sched_params *scinfo)
+{
+    int rc;
+
+    rc = libxl_vcpu_sched_params_set(ctx, domid, scinfo);
+    if (rc) {
+        fprintf(stderr, "libxl_vcpu_sched_params_set failed.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    return 0;
+}
+
+static int sched_vcpu_set_all(int domid, const libxl_vcpu_sched_params *scinfo)
+{
+    int rc;
+
+    rc = libxl_vcpu_sched_params_set_all(ctx, domid, scinfo);
+    if (rc) {
+        fprintf(stderr, "libxl_vcpu_sched_params_set_all failed.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    return 0;
+}
+
+static int sched_credit_params_set(int poolid, libxl_sched_credit_params *scinfo)
+{
+    if (libxl_sched_credit_params_set(ctx, poolid, scinfo)) {
+        fprintf(stderr, "libxl_sched_credit_params_set failed.\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+static int sched_credit_params_get(int poolid, libxl_sched_credit_params *scinfo)
+{
+    if (libxl_sched_credit_params_get(ctx, poolid, scinfo)) {
+        fprintf(stderr, "libxl_sched_credit_params_get failed.\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+static int sched_credit_domain_output(int domid)
+{
+    char *domname;
+    libxl_domain_sched_params scinfo;
+
+    if (domid < 0) {
+        printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
+        return 0;
+    }
+
+    libxl_domain_sched_params_init(&scinfo);
+    if (sched_domain_get(LIBXL_SCHEDULER_CREDIT, domid, &scinfo)) {
+        libxl_domain_sched_params_dispose(&scinfo);
+        return 1;
+    }
+    domname = libxl_domid_to_name(ctx, domid);
+    printf("%-33s %4d %6d %4d\n",
+        domname,
+        domid,
+        scinfo.weight,
+        scinfo.cap);
+    free(domname);
+    libxl_domain_sched_params_dispose(&scinfo);
+    return 0;
+}
+
+static int sched_credit_pool_output(uint32_t poolid)
+{
+    libxl_sched_credit_params scparam;
+    char *poolname;
+
+    poolname = libxl_cpupoolid_to_name(ctx, poolid);
+    if (sched_credit_params_get(poolid, &scparam)) {
+        printf("Cpupool %s: [sched params unavailable]\n",
+               poolname);
+    } else {
+        printf("Cpupool %s: tslice=%dms ratelimit=%dus\n",
+               poolname,
+               scparam.tslice_ms,
+               scparam.ratelimit_us);
+    }
+    free(poolname);
+    return 0;
+}
+
+static int sched_credit2_params_set(int poolid,
+                                    libxl_sched_credit2_params *scinfo)
+{
+    if (libxl_sched_credit2_params_set(ctx, poolid, scinfo)) {
+        fprintf(stderr, "libxl_sched_credit2_params_set failed.\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+static int sched_credit2_params_get(int poolid,
+                                    libxl_sched_credit2_params *scinfo)
+{
+    if (libxl_sched_credit2_params_get(ctx, poolid, scinfo)) {
+        fprintf(stderr, "libxl_sched_credit2_params_get failed.\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+static int sched_credit2_domain_output(int domid)
+{
+    char *domname;
+    libxl_domain_sched_params scinfo;
+
+    if (domid < 0) {
+        printf("%-33s %4s %6s\n", "Name", "ID", "Weight");
+        return 0;
+    }
+
+    libxl_domain_sched_params_init(&scinfo);
+    if (sched_domain_get(LIBXL_SCHEDULER_CREDIT2, domid, &scinfo)) {
+        libxl_domain_sched_params_dispose(&scinfo);
+        return 1;
+    }
+    domname = libxl_domid_to_name(ctx, domid);
+    printf("%-33s %4d %6d\n",
+        domname,
+        domid,
+        scinfo.weight);
+    free(domname);
+    libxl_domain_sched_params_dispose(&scinfo);
+    return 0;
+}
+
+static int sched_credit2_pool_output(uint32_t poolid)
+{
+    libxl_sched_credit2_params scparam;
+    char *poolname = libxl_cpupoolid_to_name(ctx, poolid);
+
+    if (sched_credit2_params_get(poolid, &scparam))
+        printf("Cpupool %s: [sched params unavailable]\n", poolname);
+    else
+        printf("Cpupool %s: ratelimit=%dus\n",
+               poolname, scparam.ratelimit_us);
+
+    free(poolname);
+
+    return 0;
+}
+
+static int sched_rtds_domain_output(
+    int domid)
+{
+    char *domname;
+    libxl_domain_sched_params scinfo;
+
+    if (domid < 0) {
+        printf("%-33s %4s %9s %9s\n", "Name", "ID", "Period", "Budget");
+        return 0;
+    }
+
+    libxl_domain_sched_params_init(&scinfo);
+    if (sched_domain_get(LIBXL_SCHEDULER_RTDS, domid, &scinfo)) {
+        libxl_domain_sched_params_dispose(&scinfo);
+        return 1;
+    }
+
+    domname = libxl_domid_to_name(ctx, domid);
+    printf("%-33s %4d %9d %9d\n",
+        domname,
+        domid,
+        scinfo.period,
+        scinfo.budget);
+    free(domname);
+    libxl_domain_sched_params_dispose(&scinfo);
+    return 0;
+}
+
+static int sched_rtds_vcpu_output(int domid, libxl_vcpu_sched_params *scinfo)
+{
+    char *domname;
+    int rc = 0;
+    int i;
+
+    if (domid < 0) {
+        printf("%-33s %4s %4s %9s %9s\n", "Name", "ID",
+               "VCPU", "Period", "Budget");
+        return 0;
+    }
+
+    rc = sched_vcpu_get(LIBXL_SCHEDULER_RTDS, domid, scinfo);
+    if (rc)
+        return 1;
+
+    domname = libxl_domid_to_name(ctx, domid);
+    for ( i = 0; i < scinfo->num_vcpus; i++ ) {
+        printf("%-33s %4d %4d %9"PRIu32" %9"PRIu32"\n",
+               domname,
+               domid,
+               scinfo->vcpus[i].vcpuid,
+               scinfo->vcpus[i].period,
+               scinfo->vcpus[i].budget);
+    }
+    free(domname);
+    return 0;
+}
+
+static int sched_rtds_vcpu_output_all(int domid,
+                                      libxl_vcpu_sched_params *scinfo)
+{
+    char *domname;
+    int rc = 0;
+    int i;
+
+    if (domid < 0) {
+        printf("%-33s %4s %4s %9s %9s\n", "Name", "ID",
+               "VCPU", "Period", "Budget");
+        return 0;
+    }
+
+    scinfo->num_vcpus = 0;
+    rc = sched_vcpu_get_all(LIBXL_SCHEDULER_RTDS, domid, scinfo);
+    if (rc)
+        return 1;
+
+    domname = libxl_domid_to_name(ctx, domid);
+    for ( i = 0; i < scinfo->num_vcpus; i++ ) {
+        printf("%-33s %4d %4d %9"PRIu32" %9"PRIu32"\n",
+               domname,
+               domid,
+               scinfo->vcpus[i].vcpuid,
+               scinfo->vcpus[i].period,
+               scinfo->vcpus[i].budget);
+    }
+    free(domname);
+    return 0;
+}
+
+static int sched_rtds_pool_output(uint32_t poolid)
+{
+    char *poolname;
+
+    poolname = libxl_cpupoolid_to_name(ctx, poolid);
+    printf("Cpupool %s: sched=RTDS\n", poolname);
+
+    free(poolname);
+    return 0;
+}
+
+static int sched_domain_output(libxl_scheduler sched, int (*output)(int),
+                               int (*pooloutput)(uint32_t), const char *cpupool)
+{
+    libxl_dominfo *info;
+    libxl_cpupoolinfo *poolinfo = NULL;
+    uint32_t poolid;
+    int nb_domain, n_pools = 0, i, p;
+    int rc = 0;
+
+    if (cpupool) {
+        if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool, &poolid, NULL) ||
+            !libxl_cpupoolid_is_valid(ctx, poolid)) {
+            fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
+            return 1;
+        }
+    }
+
+    info = libxl_list_domain(ctx, &nb_domain);
+    if (!info) {
+        fprintf(stderr, "libxl_list_domain failed.\n");
+        return 1;
+    }
+    poolinfo = libxl_list_cpupool(ctx, &n_pools);
+    if (!poolinfo) {
+        fprintf(stderr, "error getting cpupool info\n");
+        libxl_dominfo_list_free(info, nb_domain);
+        return 1;
+    }
+
+    for (p = 0; !rc && (p < n_pools); p++) {
+        if ((poolinfo[p].sched != sched) ||
+            (cpupool && (poolid != poolinfo[p].poolid)))
+            continue;
+
+        pooloutput(poolinfo[p].poolid);
+
+        output(-1);
+        for (i = 0; i < nb_domain; i++) {
+            if (info[i].cpupool != poolinfo[p].poolid)
+                continue;
+            rc = output(info[i].domid);
+            if (rc)
+                break;
+        }
+    }
+
+    libxl_cpupoolinfo_list_free(poolinfo, n_pools);
+    libxl_dominfo_list_free(info, nb_domain);
+    return 0;
+}
+
+static int sched_vcpu_output(libxl_scheduler sched,
+                             int (*output)(int, libxl_vcpu_sched_params *),
+                             int (*pooloutput)(uint32_t), const char *cpupool)
+{
+    libxl_dominfo *info;
+    libxl_cpupoolinfo *poolinfo = NULL;
+    uint32_t poolid;
+    int nb_domain, n_pools = 0, i, p;
+    int rc = 0;
+
+    if (cpupool) {
+        if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool, &poolid, NULL)
+            || !libxl_cpupoolid_is_valid(ctx, poolid)) {
+            fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
+            return 1;
+        }
+    }
+
+    info = libxl_list_domain(ctx, &nb_domain);
+    if (!info) {
+        fprintf(stderr, "libxl_list_domain failed.\n");
+        return 1;
+    }
+    poolinfo = libxl_list_cpupool(ctx, &n_pools);
+    if (!poolinfo) {
+        fprintf(stderr, "error getting cpupool info\n");
+        libxl_dominfo_list_free(info, nb_domain);
+        return 1;
+    }
+
+    for (p = 0; !rc && (p < n_pools); p++) {
+        if ((poolinfo[p].sched != sched) ||
+            (cpupool && (poolid != poolinfo[p].poolid)))
+            continue;
+
+        pooloutput(poolinfo[p].poolid);
+
+        output(-1, NULL);
+        for (i = 0; i < nb_domain; i++) {
+            libxl_vcpu_sched_params scinfo;
+            if (info[i].cpupool != poolinfo[p].poolid)
+                continue;
+            libxl_vcpu_sched_params_init(&scinfo);
+            rc = output(info[i].domid, &scinfo);
+            libxl_vcpu_sched_params_dispose(&scinfo);
+            if (rc)
+                break;
+        }
+    }
+
+    libxl_cpupoolinfo_list_free(poolinfo, n_pools);
+    libxl_dominfo_list_free(info, nb_domain);
+    return 0;
+}
+
+/*
+ * <nothing>             : List all domain params and sched params from all pools
+ * -d [domid]            : List domain params for domain
+ * -d [domid] [params]   : Set domain params for domain
+ * -p [pool]             : list all domains and sched params for pool
+ * -s                    : List sched params for poolid 0
+ * -s [params]           : Set sched params for poolid 0
+ * -p [pool] -s          : List sched params for pool
+ * -p [pool] -s [params] : Set sched params for pool
+ * -p [pool] -d...       : Illegal
+ */
+int main_sched_credit(int argc, char **argv)
+{
+    const char *dom = NULL;
+    const char *cpupool = NULL;
+    int weight = 256, cap = 0;
+    int tslice = 0, ratelimit = 0;
+    bool opt_w = false, opt_c = false;
+    bool opt_t = false, opt_r = false;
+    bool opt_s = false;
+    int opt, rc;
+    static struct option opts[] = {
+        {"domain", 1, 0, 'd'},
+        {"weight", 1, 0, 'w'},
+        {"cap", 1, 0, 'c'},
+        {"schedparam", 0, 0, 's'},
+        {"tslice_ms", 1, 0, 't'},
+        {"ratelimit_us", 1, 0, 'r'},
+        {"cpupool", 1, 0, 'p'},
+        COMMON_LONG_OPTS
+    };
+
+    SWITCH_FOREACH_OPT(opt, "d:w:c:p:t:r:s", opts, "sched-credit", 0) {
+    case 'd':
+        dom = optarg;
+        break;
+    case 'w':
+        weight = strtol(optarg, NULL, 10);
+        opt_w = true;
+        break;
+    case 'c':
+        cap = strtol(optarg, NULL, 10);
+        opt_c = true;
+        break;
+    case 't':
+        tslice = strtol(optarg, NULL, 10);
+        opt_t = true;
+        break;
+    case 'r':
+        ratelimit = strtol(optarg, NULL, 10);
+        opt_r = true;
+        break;
+    case 's':
+        opt_s = true;
+        break;
+    case 'p':
+        cpupool = optarg;
+        break;
+    }
+
+    if ((cpupool || opt_s) && (dom || opt_w || opt_c)) {
+        fprintf(stderr, "Specifying a cpupool or schedparam is not "
+                "allowed with domain options.\n");
+        return EXIT_FAILURE;
+    }
+    if (!dom && (opt_w || opt_c)) {
+        fprintf(stderr, "Must specify a domain.\n");
+        return EXIT_FAILURE;
+    }
+    if (!opt_s && (opt_t || opt_r)) {
+        fprintf(stderr, "Must specify schedparam to set schedule "
+                "parameter values.\n");
+        return EXIT_FAILURE;
+    }
+
+    if (opt_s) {
+        libxl_sched_credit_params scparam;
+        uint32_t poolid = 0;
+
+        if (cpupool) {
+            if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool,
+                                                     &poolid, NULL) ||
+                !libxl_cpupoolid_is_valid(ctx, poolid)) {
+                fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
+                return EXIT_FAILURE;
+            }
+        }
+
+        if (!opt_t && !opt_r) { /* Output scheduling parameters */
+            if (sched_credit_pool_output(poolid))
+                return EXIT_FAILURE;
+        } else { /* Set scheduling parameters*/
+            if (sched_credit_params_get(poolid, &scparam))
+                return EXIT_FAILURE;
+
+            if (opt_t)
+                scparam.tslice_ms = tslice;
+
+            if (opt_r)
+                scparam.ratelimit_us = ratelimit;
+
+            if (sched_credit_params_set(poolid, &scparam))
+                return EXIT_FAILURE;
+        }
+    } else if (!dom) { /* list all domain's credit scheduler info */
+        if (sched_domain_output(LIBXL_SCHEDULER_CREDIT,
+                                sched_credit_domain_output,
+                                sched_credit_pool_output,
+                                cpupool))
+            return EXIT_FAILURE;
+    } else {
+        uint32_t domid = xfind_domain(dom);
+
+        if (!opt_w && !opt_c) { /* output credit scheduler info */
+            sched_credit_domain_output(-1);
+            if (sched_credit_domain_output(domid))
+                return EXIT_FAILURE;
+        } else { /* set credit scheduler paramaters */
+            libxl_domain_sched_params scinfo;
+            libxl_domain_sched_params_init(&scinfo);
+            scinfo.sched = LIBXL_SCHEDULER_CREDIT;
+            if (opt_w)
+                scinfo.weight = weight;
+            if (opt_c)
+                scinfo.cap = cap;
+            rc = sched_domain_set(domid, &scinfo);
+            libxl_domain_sched_params_dispose(&scinfo);
+            if (rc)
+                return EXIT_FAILURE;
+        }
+    }
+
+    return EXIT_SUCCESS;
+}
+
+int main_sched_credit2(int argc, char **argv)
+{
+    const char *dom = NULL;
+    const char *cpupool = NULL;
+    int ratelimit = 0;
+    int weight = 256;
+    bool opt_s = false;
+    bool opt_r = false;
+    bool opt_w = false;
+    int opt, rc;
+    static struct option opts[] = {
+        {"domain", 1, 0, 'd'},
+        {"weight", 1, 0, 'w'},
+        {"schedparam", 0, 0, 's'},
+        {"ratelimit_us", 1, 0, 'r'},
+        {"cpupool", 1, 0, 'p'},
+        COMMON_LONG_OPTS
+    };
+
+    SWITCH_FOREACH_OPT(opt, "d:w:p:r:s", opts, "sched-credit2", 0) {
+    case 'd':
+        dom = optarg;
+        break;
+    case 'w':
+        weight = strtol(optarg, NULL, 10);
+        opt_w = true;
+        break;
+    case 's':
+        opt_s = true;
+        break;
+    case 'r':
+        ratelimit = strtol(optarg, NULL, 10);
+        opt_r = true;
+        break;
+    case 'p':
+        cpupool = optarg;
+        break;
+    }
+
+    if (cpupool && (dom || opt_w)) {
+        fprintf(stderr, "Specifying a cpupool is not allowed with other "
+                "options.\n");
+        return EXIT_FAILURE;
+    }
+    if (!dom && opt_w) {
+        fprintf(stderr, "Must specify a domain.\n");
+        return EXIT_FAILURE;
+    }
+
+    if (opt_s) {
+        libxl_sched_credit2_params scparam;
+        uint32_t poolid = 0;
+
+        if (cpupool) {
+            if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool,
+                                                     &poolid, NULL) ||
+                !libxl_cpupoolid_is_valid(ctx, poolid)) {
+                fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
+                return EXIT_FAILURE;
+            }
+        }
+
+        if (!opt_r) { /* Output scheduling parameters */
+            if (sched_credit2_pool_output(poolid))
+                return EXIT_FAILURE;
+        } else {      /* Set scheduling parameters (so far, just ratelimit) */
+            scparam.ratelimit_us = ratelimit;
+            if (sched_credit2_params_set(poolid, &scparam))
+                return EXIT_FAILURE;
+        }
+    } else if (!dom) { /* list all domain's credit scheduler info */
+        if (sched_domain_output(LIBXL_SCHEDULER_CREDIT2,
+                                sched_credit2_domain_output,
+                                sched_credit2_pool_output,
+                                cpupool))
+            return EXIT_FAILURE;
+    } else {
+        uint32_t domid = xfind_domain(dom);
+
+        if (!opt_w) { /* output credit2 scheduler info */
+            sched_credit2_domain_output(-1);
+            if (sched_credit2_domain_output(domid))
+                return EXIT_FAILURE;
+        } else { /* set credit2 scheduler paramaters */
+            libxl_domain_sched_params scinfo;
+            libxl_domain_sched_params_init(&scinfo);
+            scinfo.sched = LIBXL_SCHEDULER_CREDIT2;
+            if (opt_w)
+                scinfo.weight = weight;
+            rc = sched_domain_set(domid, &scinfo);
+            libxl_domain_sched_params_dispose(&scinfo);
+            if (rc)
+                return EXIT_FAILURE;
+        }
+    }
+
+    return EXIT_SUCCESS;
+}
+
+/*
+ * <nothing>            : List all domain paramters and sched params
+ * -d [domid]           : List default domain params for domain
+ * -d [domid] [params]  : Set domain params for domain
+ * -d [domid] -v [vcpuid 1] -v [vcpuid 2] ...  :
+ * List per-VCPU params for domain
+ * -d [domid] -v all  : List all per-VCPU params for domain
+ * -v all  : List all per-VCPU params for all domains
+ * -d [domid] -v [vcpuid 1] [params] -v [vcpuid 2] [params] ...  :
+ * Set per-VCPU params for domain
+ * -d [domid] -v all [params]  : Set all per-VCPU params for domain
+ */
+int main_sched_rtds(int argc, char **argv)
+{
+    const char *dom = NULL;
+    const char *cpupool = NULL;
+    int *vcpus = (int *)xmalloc(sizeof(int)); /* IDs of VCPUs that change */
+    int *periods = (int *)xmalloc(sizeof(int)); /* period is in microsecond */
+    int *budgets = (int *)xmalloc(sizeof(int)); /* budget is in microsecond */
+    int v_size = 1; /* size of vcpus array */
+    int p_size = 1; /* size of periods array */
+    int b_size = 1; /* size of budgets array */
+    int v_index = 0; /* index in vcpus array */
+    int p_index =0; /* index in periods array */
+    int b_index =0; /* index for in budgets array */
+    bool opt_p = false;
+    bool opt_b = false;
+    bool opt_v = false;
+    bool opt_all = false; /* output per-dom parameters */
+    int opt, i, rc, r;
+    static struct option opts[] = {
+        {"domain", 1, 0, 'd'},
+        {"period", 1, 0, 'p'},
+        {"budget", 1, 0, 'b'},
+        {"vcpuid",1, 0, 'v'},
+        {"cpupool", 1, 0, 'c'},
+        COMMON_LONG_OPTS
+    };
+
+    SWITCH_FOREACH_OPT(opt, "d:p:b:v:c", opts, "sched-rtds", 0) {
+    case 'd':
+        dom = optarg;
+        break;
+    case 'p':
+        if (p_index >= p_size) {
+            /*
+             * periods array is full
+             * double the array size for new elements
+             */
+            p_size *= 2;
+            periods = xrealloc(periods, p_size);
+        }
+        periods[p_index++] = strtol(optarg, NULL, 10);
+        opt_p = 1;
+        break;
+    case 'b':
+        if (b_index >= b_size) { /* budgets array is full */
+            b_size *= 2;
+            budgets = xrealloc(budgets, b_size);
+        }
+        budgets[b_index++] = strtol(optarg, NULL, 10);
+        opt_b = 1;
+        break;
+    case 'v':
+        if (!strcmp(optarg, "all")) { /* get or set all vcpus of a domain */
+            opt_all = 1;
+            break;
+        }
+        if (v_index >= v_size) { /* vcpus array is full */
+            v_size *= 2;
+            vcpus = xrealloc(vcpus, v_size);
+        }
+        vcpus[v_index++] = strtol(optarg, NULL, 10);
+        opt_v = 1;
+        break;
+    case 'c':
+        cpupool = optarg;
+        break;
+    }
+
+    if (cpupool && (dom || opt_p || opt_b || opt_v || opt_all)) {
+        fprintf(stderr, "Specifying a cpupool is not allowed with "
+                "other options.\n");
+        r = EXIT_FAILURE;
+        goto out;
+    }
+    if (!dom && (opt_p || opt_b || opt_v)) {
+        fprintf(stderr, "Missing parameters.\n");
+        r = EXIT_FAILURE;
+        goto out;
+    }
+    if (dom && !opt_v && !opt_all && (opt_p || opt_b)) {
+        fprintf(stderr, "Must specify VCPU.\n");
+        r = EXIT_FAILURE;
+        goto out;
+    }
+    if (opt_v && opt_all) {
+        fprintf(stderr, "Incorrect VCPU IDs.\n");
+        r = EXIT_FAILURE;
+        goto out;
+    }
+    if (((v_index > b_index) && opt_b) || ((v_index > p_index) && opt_p)
+        || p_index != b_index) {
+        fprintf(stderr, "Incorrect number of period and budget\n");
+        r = EXIT_FAILURE;
+        goto out;
+    }
+
+    if ((!dom) && opt_all) {
+        /* get all domain's per-vcpu rtds scheduler parameters */
+        rc = -sched_vcpu_output(LIBXL_SCHEDULER_RTDS,
+                                sched_rtds_vcpu_output_all,
+                                sched_rtds_pool_output,
+                                cpupool);
+        if (rc) {
+            r = EXIT_FAILURE;
+            goto out;
+        }
+    } else if (!dom && !opt_all) {
+        /* list all domain's default scheduling parameters */
+        rc = -sched_domain_output(LIBXL_SCHEDULER_RTDS,
+                                  sched_rtds_domain_output,
+                                  sched_rtds_pool_output,
+                                  cpupool);
+        if (rc) {
+            r = EXIT_FAILURE;
+            goto out;
+        }
+    } else {
+        uint32_t domid = xfind_domain(dom);
+        if (!opt_v && !opt_all) { /* output default scheduling parameters */
+            sched_rtds_domain_output(-1);
+            rc = -sched_rtds_domain_output(domid);
+            if (rc) {
+                r = EXIT_FAILURE;
+                goto out;
+            }
+        } else if (!opt_p && !opt_b) {
+            /* get per-vcpu rtds scheduling parameters */
+            libxl_vcpu_sched_params scinfo;
+            libxl_vcpu_sched_params_init(&scinfo);
+            sched_rtds_vcpu_output(-1, &scinfo);
+            scinfo.num_vcpus = v_index;
+            if (v_index > 0) {
+                scinfo.vcpus = (libxl_sched_params *)
+                               xmalloc(sizeof(libxl_sched_params) * (v_index));
+                for (i = 0; i < v_index; i++)
+                    scinfo.vcpus[i].vcpuid = vcpus[i];
+                rc = -sched_rtds_vcpu_output(domid, &scinfo);
+            } else /* get params for all vcpus */
+                rc = -sched_rtds_vcpu_output_all(domid, &scinfo);
+            libxl_vcpu_sched_params_dispose(&scinfo);
+            if (rc) {
+                r = EXIT_FAILURE;
+                goto out;
+            }
+    } else if (opt_v || opt_all) {
+            /* set per-vcpu rtds scheduling parameters */
+            libxl_vcpu_sched_params scinfo;
+            libxl_vcpu_sched_params_init(&scinfo);
+            scinfo.sched = LIBXL_SCHEDULER_RTDS;
+            if (v_index > 0) {
+                scinfo.num_vcpus = v_index;
+                scinfo.vcpus = (libxl_sched_params *)
+                               xmalloc(sizeof(libxl_sched_params) * (v_index));
+                for (i = 0; i < v_index; i++) {
+                    scinfo.vcpus[i].vcpuid = vcpus[i];
+                    scinfo.vcpus[i].period = periods[i];
+                    scinfo.vcpus[i].budget = budgets[i];
+                }
+                rc = sched_vcpu_set(domid, &scinfo);
+            } else { /* set params for all vcpus */
+                scinfo.num_vcpus = 1;
+                scinfo.vcpus = (libxl_sched_params *)
+                               xmalloc(sizeof(libxl_sched_params));
+                scinfo.vcpus[0].period = periods[0];
+                scinfo.vcpus[0].budget = budgets[0];
+                rc = sched_vcpu_set_all(domid, &scinfo);
+            }
+
+            libxl_vcpu_sched_params_dispose(&scinfo);
+            if (rc) {
+                r = EXIT_FAILURE;
+                goto out;
+            }
+        }
+    }
+
+    r = EXIT_SUCCESS;
+out:
+    free(vcpus);
+    free(periods);
+    free(budgets);
+    return r;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 18/29] xl: split out pci related code
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (16 preceding siblings ...)
  2017-02-24 16:13 ` [PATCH 17/29] xl: split out scheduler " Wei Liu
@ 2017-02-24 16:13 ` Wei Liu
  2017-02-27 16:01   ` Ian Jackson
  2017-02-24 16:13 ` [PATCH 19/29] xl: split out vcpu " Wei Liu
                   ` (10 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:13 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   2 +-
 tools/xl/xl_cmdimpl.c | 247 --------------------------------------------
 tools/xl/xl_pci.c     | 278 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 279 insertions(+), 248 deletions(-)
 create mode 100644 tools/xl/xl_pci.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index 8aa294d5a0..0af1e92b65 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -18,7 +18,7 @@ CFLAGS_XL += -Wshadow
 XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
 XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
 XL_OBJS += xl_vtpm.o xl_block.o xl_nic.o xl_usb.o
-XL_OBJS += xl_sched.o
+XL_OBJS += xl_sched.o xl_pci.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index 7d6de3957e..b32233e95e 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -1347,253 +1347,6 @@ int main_vncviewer(int argc, char **argv)
     return EXIT_SUCCESS;
 }
 
-static void pcilist(uint32_t domid)
-{
-    libxl_device_pci *pcidevs;
-    int num, i;
-
-    pcidevs = libxl_device_pci_list(ctx, domid, &num);
-    if (pcidevs == NULL)
-        return;
-    printf("Vdev Device\n");
-    for (i = 0; i < num; i++) {
-        printf("%02x.%01x %04x:%02x:%02x.%01x\n",
-               (pcidevs[i].vdevfn >> 3) & 0x1f, pcidevs[i].vdevfn & 0x7,
-               pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
-        libxl_device_pci_dispose(&pcidevs[i]);
-    }
-    free(pcidevs);
-}
-
-int main_pcilist(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "pci-list", 1) {
-        /* No options */
-    }
-
-    domid = xfind_domain(argv[optind]);
-
-    pcilist(domid);
-    return 0;
-}
-
-static int pcidetach(uint32_t domid, const char *bdf, int force)
-{
-    libxl_device_pci pcidev;
-    XLU_Config *config;
-    int r = 0;
-
-    libxl_device_pci_init(&pcidev);
-
-    config = xlu_cfg_init(stderr, "command line");
-    if (!config) { perror("xlu_cfg_inig"); exit(-1); }
-
-    if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
-        fprintf(stderr, "pci-detach: malformed BDF specification \"%s\"\n", bdf);
-        exit(2);
-    }
-    if (force) {
-        if (libxl_device_pci_destroy(ctx, domid, &pcidev, 0))
-            r = 1;
-    } else {
-        if (libxl_device_pci_remove(ctx, domid, &pcidev, 0))
-            r = 1;
-    }
-
-    libxl_device_pci_dispose(&pcidev);
-    xlu_cfg_destroy(config);
-
-    return r;
-}
-
-int main_pcidetach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    int force = 0;
-    const char *bdf = NULL;
-
-    SWITCH_FOREACH_OPT(opt, "f", NULL, "pci-detach", 2) {
-    case 'f':
-        force = 1;
-        break;
-    }
-
-    domid = xfind_domain(argv[optind]);
-    bdf = argv[optind + 1];
-
-    if (pcidetach(domid, bdf, force))
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-static int pciattach(uint32_t domid, const char *bdf, const char *vs)
-{
-    libxl_device_pci pcidev;
-    XLU_Config *config;
-    int r = 0;
-
-    libxl_device_pci_init(&pcidev);
-
-    config = xlu_cfg_init(stderr, "command line");
-    if (!config) { perror("xlu_cfg_inig"); exit(-1); }
-
-    if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
-        fprintf(stderr, "pci-attach: malformed BDF specification \"%s\"\n", bdf);
-        exit(2);
-    }
-
-    if (libxl_device_pci_add(ctx, domid, &pcidev, 0))
-        r = 1;
-
-    libxl_device_pci_dispose(&pcidev);
-    xlu_cfg_destroy(config);
-
-    return r;
-}
-
-int main_pciattach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    const char *bdf = NULL, *vs = NULL;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "pci-attach", 2) {
-        /* No options */
-    }
-
-    domid = xfind_domain(argv[optind]);
-    bdf = argv[optind + 1];
-
-    if (optind + 1 < argc)
-        vs = argv[optind + 2];
-
-    if (pciattach(domid, bdf, vs))
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-static void pciassignable_list(void)
-{
-    libxl_device_pci *pcidevs;
-    int num, i;
-
-    pcidevs = libxl_device_pci_assignable_list(ctx, &num);
-
-    if ( pcidevs == NULL )
-        return;
-    for (i = 0; i < num; i++) {
-        printf("%04x:%02x:%02x.%01x\n",
-               pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
-        libxl_device_pci_dispose(&pcidevs[i]);
-    }
-    free(pcidevs);
-}
-
-int main_pciassignable_list(int argc, char **argv)
-{
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "pci-assignable-list", 0) {
-        /* No options */
-    }
-
-    pciassignable_list();
-    return 0;
-}
-
-static int pciassignable_add(const char *bdf, int rebind)
-{
-    libxl_device_pci pcidev;
-    XLU_Config *config;
-    int r = 0;
-
-    libxl_device_pci_init(&pcidev);
-
-    config = xlu_cfg_init(stderr, "command line");
-    if (!config) { perror("xlu_cfg_init"); exit(-1); }
-
-    if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
-        fprintf(stderr, "pci-assignable-add: malformed BDF specification \"%s\"\n", bdf);
-        exit(2);
-    }
-
-    if (libxl_device_pci_assignable_add(ctx, &pcidev, rebind))
-        r = 1;
-
-    libxl_device_pci_dispose(&pcidev);
-    xlu_cfg_destroy(config);
-
-    return r;
-}
-
-int main_pciassignable_add(int argc, char **argv)
-{
-    int opt;
-    const char *bdf = NULL;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "pci-assignable-add", 1) {
-        /* No options */
-    }
-
-    bdf = argv[optind];
-
-    if (pciassignable_add(bdf, 1))
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-static int pciassignable_remove(const char *bdf, int rebind)
-{
-    libxl_device_pci pcidev;
-    XLU_Config *config;
-    int r = 0;
-
-    libxl_device_pci_init(&pcidev);
-
-    config = xlu_cfg_init(stderr, "command line");
-    if (!config) { perror("xlu_cfg_init"); exit(-1); }
-
-    if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
-        fprintf(stderr, "pci-assignable-remove: malformed BDF specification \"%s\"\n", bdf);
-        exit(2);
-    }
-
-    if (libxl_device_pci_assignable_remove(ctx, &pcidev, rebind))
-        r = 1;
-
-    libxl_device_pci_dispose(&pcidev);
-    xlu_cfg_destroy(config);
-
-    return r;
-}
-
-int main_pciassignable_remove(int argc, char **argv)
-{
-    int opt;
-    const char *bdf = NULL;
-    int rebind = 0;
-
-    SWITCH_FOREACH_OPT(opt, "r", NULL, "pci-assignable-remove", 1) {
-    case 'r':
-        rebind=1;
-        break;
-    }
-
-    bdf = argv[optind];
-
-    if (pciassignable_remove(bdf, rebind))
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
 static void pause_domain(uint32_t domid)
 {
     libxl_domain_pause(ctx, domid);
diff --git a/tools/xl/xl_pci.c b/tools/xl/xl_pci.c
new file mode 100644
index 0000000000..2e0f6fdda5
--- /dev/null
+++ b/tools/xl/xl_pci.c
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <stdlib.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+static void pcilist(uint32_t domid)
+{
+    libxl_device_pci *pcidevs;
+    int num, i;
+
+    pcidevs = libxl_device_pci_list(ctx, domid, &num);
+    if (pcidevs == NULL)
+        return;
+    printf("Vdev Device\n");
+    for (i = 0; i < num; i++) {
+        printf("%02x.%01x %04x:%02x:%02x.%01x\n",
+               (pcidevs[i].vdevfn >> 3) & 0x1f, pcidevs[i].vdevfn & 0x7,
+               pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
+        libxl_device_pci_dispose(&pcidevs[i]);
+    }
+    free(pcidevs);
+}
+
+int main_pcilist(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "pci-list", 1) {
+        /* No options */
+    }
+
+    domid = xfind_domain(argv[optind]);
+
+    pcilist(domid);
+    return 0;
+}
+
+static int pcidetach(uint32_t domid, const char *bdf, int force)
+{
+    libxl_device_pci pcidev;
+    XLU_Config *config;
+    int r = 0;
+
+    libxl_device_pci_init(&pcidev);
+
+    config = xlu_cfg_init(stderr, "command line");
+    if (!config) { perror("xlu_cfg_inig"); exit(-1); }
+
+    if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
+        fprintf(stderr, "pci-detach: malformed BDF specification \"%s\"\n", bdf);
+        exit(2);
+    }
+    if (force) {
+        if (libxl_device_pci_destroy(ctx, domid, &pcidev, 0))
+            r = 1;
+    } else {
+        if (libxl_device_pci_remove(ctx, domid, &pcidev, 0))
+            r = 1;
+    }
+
+    libxl_device_pci_dispose(&pcidev);
+    xlu_cfg_destroy(config);
+
+    return r;
+}
+
+int main_pcidetach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    int force = 0;
+    const char *bdf = NULL;
+
+    SWITCH_FOREACH_OPT(opt, "f", NULL, "pci-detach", 2) {
+    case 'f':
+        force = 1;
+        break;
+    }
+
+    domid = xfind_domain(argv[optind]);
+    bdf = argv[optind + 1];
+
+    if (pcidetach(domid, bdf, force))
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+static int pciattach(uint32_t domid, const char *bdf, const char *vs)
+{
+    libxl_device_pci pcidev;
+    XLU_Config *config;
+    int r = 0;
+
+    libxl_device_pci_init(&pcidev);
+
+    config = xlu_cfg_init(stderr, "command line");
+    if (!config) { perror("xlu_cfg_inig"); exit(-1); }
+
+    if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
+        fprintf(stderr, "pci-attach: malformed BDF specification \"%s\"\n", bdf);
+        exit(2);
+    }
+
+    if (libxl_device_pci_add(ctx, domid, &pcidev, 0))
+        r = 1;
+
+    libxl_device_pci_dispose(&pcidev);
+    xlu_cfg_destroy(config);
+
+    return r;
+}
+
+int main_pciattach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    const char *bdf = NULL, *vs = NULL;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "pci-attach", 2) {
+        /* No options */
+    }
+
+    domid = xfind_domain(argv[optind]);
+    bdf = argv[optind + 1];
+
+    if (optind + 1 < argc)
+        vs = argv[optind + 2];
+
+    if (pciattach(domid, bdf, vs))
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+static void pciassignable_list(void)
+{
+    libxl_device_pci *pcidevs;
+    int num, i;
+
+    pcidevs = libxl_device_pci_assignable_list(ctx, &num);
+
+    if ( pcidevs == NULL )
+        return;
+    for (i = 0; i < num; i++) {
+        printf("%04x:%02x:%02x.%01x\n",
+               pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
+        libxl_device_pci_dispose(&pcidevs[i]);
+    }
+    free(pcidevs);
+}
+
+int main_pciassignable_list(int argc, char **argv)
+{
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "pci-assignable-list", 0) {
+        /* No options */
+    }
+
+    pciassignable_list();
+    return 0;
+}
+
+static int pciassignable_add(const char *bdf, int rebind)
+{
+    libxl_device_pci pcidev;
+    XLU_Config *config;
+    int r = 0;
+
+    libxl_device_pci_init(&pcidev);
+
+    config = xlu_cfg_init(stderr, "command line");
+    if (!config) { perror("xlu_cfg_init"); exit(-1); }
+
+    if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
+        fprintf(stderr, "pci-assignable-add: malformed BDF specification \"%s\"\n", bdf);
+        exit(2);
+    }
+
+    if (libxl_device_pci_assignable_add(ctx, &pcidev, rebind))
+        r = 1;
+
+    libxl_device_pci_dispose(&pcidev);
+    xlu_cfg_destroy(config);
+
+    return r;
+}
+
+int main_pciassignable_add(int argc, char **argv)
+{
+    int opt;
+    const char *bdf = NULL;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "pci-assignable-add", 1) {
+        /* No options */
+    }
+
+    bdf = argv[optind];
+
+    if (pciassignable_add(bdf, 1))
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+static int pciassignable_remove(const char *bdf, int rebind)
+{
+    libxl_device_pci pcidev;
+    XLU_Config *config;
+    int r = 0;
+
+    libxl_device_pci_init(&pcidev);
+
+    config = xlu_cfg_init(stderr, "command line");
+    if (!config) { perror("xlu_cfg_init"); exit(-1); }
+
+    if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
+        fprintf(stderr, "pci-assignable-remove: malformed BDF specification \"%s\"\n", bdf);
+        exit(2);
+    }
+
+    if (libxl_device_pci_assignable_remove(ctx, &pcidev, rebind))
+        r = 1;
+
+    libxl_device_pci_dispose(&pcidev);
+    xlu_cfg_destroy(config);
+
+    return r;
+}
+
+int main_pciassignable_remove(int argc, char **argv)
+{
+    int opt;
+    const char *bdf = NULL;
+    int rebind = 0;
+
+    SWITCH_FOREACH_OPT(opt, "r", NULL, "pci-assignable-remove", 1) {
+    case 'r':
+        rebind=1;
+        break;
+    }
+
+    bdf = argv[optind];
+
+    if (pciassignable_remove(bdf, rebind))
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 19/29] xl: split out vcpu related code
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (17 preceding siblings ...)
  2017-02-24 16:13 ` [PATCH 18/29] xl: split out pci " Wei Liu
@ 2017-02-24 16:13 ` Wei Liu
  2017-02-27 15:59   ` Ian Jackson
  2017-02-24 16:13 ` [PATCH 20/29] xl: split out cd " Wei Liu
                   ` (9 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:13 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   2 +-
 tools/xl/xl_cmdimpl.c | 306 ---------------------------------------------
 tools/xl/xl_vcpu.c    | 337 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 338 insertions(+), 307 deletions(-)
 create mode 100644 tools/xl/xl_vcpu.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index 0af1e92b65..e6e8cef710 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -18,7 +18,7 @@ CFLAGS_XL += -Wshadow
 XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
 XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
 XL_OBJS += xl_vtpm.o xl_block.o xl_nic.o xl_usb.o
-XL_OBJS += xl_sched.o xl_pci.o
+XL_OBJS += xl_sched.o xl_pci.o xl_vcpu.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index b32233e95e..faeac675ad 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -2885,312 +2885,6 @@ int main_button_press(int argc, char **argv)
     return 0;
 }
 
-static void print_vcpuinfo(uint32_t tdomid,
-                           const libxl_vcpuinfo *vcpuinfo,
-                           uint32_t nr_cpus)
-{
-    char *domname;
-
-    /*      NAME  ID  VCPU */
-    domname = libxl_domid_to_name(ctx, tdomid);
-    printf("%-32s %5u %5u",
-           domname, tdomid, vcpuinfo->vcpuid);
-    free(domname);
-    if (!vcpuinfo->online) {
-        /*      CPU STA */
-        printf("%5c %3c%cp ", '-', '-', '-');
-    } else {
-        /*      CPU STA */
-        printf("%5u %3c%c- ", vcpuinfo->cpu,
-               vcpuinfo->running ? 'r' : '-',
-               vcpuinfo->blocked ? 'b' : '-');
-    }
-    /*      TIM */
-    printf("%9.1f  ", ((float)vcpuinfo->vcpu_time / 1e9));
-    /* CPU HARD AND SOFT AFFINITY */
-    print_bitmap(vcpuinfo->cpumap.map, nr_cpus, stdout);
-    printf(" / ");
-    print_bitmap(vcpuinfo->cpumap_soft.map, nr_cpus, stdout);
-    printf("\n");
-}
-
-static void print_domain_vcpuinfo(uint32_t domid, uint32_t nr_cpus)
-{
-    libxl_vcpuinfo *vcpuinfo;
-    int i, nb_vcpu, nrcpus;
-
-    vcpuinfo = libxl_list_vcpu(ctx, domid, &nb_vcpu, &nrcpus);
-
-    if (!vcpuinfo)
-        return;
-
-    for (i = 0; i < nb_vcpu; i++) {
-        print_vcpuinfo(domid, &vcpuinfo[i], nr_cpus);
-    }
-
-    libxl_vcpuinfo_list_free(vcpuinfo, nb_vcpu);
-}
-
-static void vcpulist(int argc, char **argv)
-{
-    libxl_dominfo *dominfo;
-    libxl_physinfo physinfo;
-    int i, nb_domain;
-
-    if (libxl_get_physinfo(ctx, &physinfo) != 0) {
-        fprintf(stderr, "libxl_physinfo failed.\n");
-        goto vcpulist_out;
-    }
-
-    printf("%-32s %5s %5s %5s %5s %9s %s\n",
-           "Name", "ID", "VCPU", "CPU", "State", "Time(s)",
-           "Affinity (Hard / Soft)");
-    if (!argc) {
-        if (!(dominfo = libxl_list_domain(ctx, &nb_domain))) {
-            fprintf(stderr, "libxl_list_domain failed.\n");
-            goto vcpulist_out;
-        }
-
-        for (i = 0; i<nb_domain; i++)
-            print_domain_vcpuinfo(dominfo[i].domid, physinfo.nr_cpus);
-
-        libxl_dominfo_list_free(dominfo, nb_domain);
-    } else {
-        for (; argc > 0; ++argv, --argc) {
-            uint32_t domid = xfind_domain(*argv);
-            print_domain_vcpuinfo(domid, physinfo.nr_cpus);
-        }
-    }
-  vcpulist_out:
-    libxl_physinfo_dispose(&physinfo);
-}
-
-int main_vcpulist(int argc, char **argv)
-{
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "vcpu-list", 0) {
-        /* No options */
-    }
-
-    vcpulist(argc - optind, argv + optind);
-    return EXIT_SUCCESS;
-}
-
-int main_vcpupin(int argc, char **argv)
-{
-    static struct option opts[] = {
-        {"force", 0, 0, 'f'},
-        COMMON_LONG_OPTS
-    };
-    libxl_vcpuinfo *vcpuinfo;
-    libxl_bitmap cpumap_hard, cpumap_soft;;
-    libxl_bitmap *soft = &cpumap_soft, *hard = &cpumap_hard;
-    uint32_t domid;
-    /*
-     * int would be enough for vcpuid, but we don't want to
-     * mess aroung range checking the return value of strtol().
-     */
-    long vcpuid;
-    const char *vcpu, *hard_str, *soft_str;
-    char *endptr;
-    int opt, nb_cpu, nb_vcpu, rc = EXIT_FAILURE;
-    bool force = false;
-
-    libxl_bitmap_init(&cpumap_hard);
-    libxl_bitmap_init(&cpumap_soft);
-
-    SWITCH_FOREACH_OPT(opt, "f", opts, "vcpu-pin", 3) {
-    case 'f':
-        force = true;
-        break;
-    default:
-        break;
-    }
-
-    domid = xfind_domain(argv[optind]);
-    vcpu = argv[optind+1];
-    hard_str = argv[optind+2];
-    soft_str = (argc > optind+3) ? argv[optind+3] : NULL;
-
-    /* Figure out with which vCPU we are dealing with */
-    vcpuid = strtol(vcpu, &endptr, 10);
-    if (vcpu == endptr || vcpuid < 0) {
-        if (strcmp(vcpu, "all")) {
-            fprintf(stderr, "Error: Invalid argument %s as VCPU.\n", vcpu);
-            goto out;
-        }
-        if (force) {
-            fprintf(stderr, "Error: --force and 'all' as VCPU not allowed.\n");
-            goto out;
-        }
-        vcpuid = -1;
-    }
-
-    if (libxl_cpu_bitmap_alloc(ctx, &cpumap_hard, 0) ||
-        libxl_cpu_bitmap_alloc(ctx, &cpumap_soft, 0))
-        goto out;
-
-    /*
-     * Syntax is: xl vcpu-pin <domid> <vcpu> <hard> <soft>
-     * We want to handle all the following cases ('-' means
-     * "leave it alone"):
-     *  xl vcpu-pin 0 3 3,4
-     *  xl vcpu-pin 0 3 3,4 -
-     *  xl vcpu-pin 0 3 - 6-9
-     *  xl vcpu-pin 0 3 3,4 6-9
-     */
-
-    /*
-     * Hard affinity is always present. However, if it's "-", all we need
-     * is passing a NULL pointer to the libxl_set_vcpuaffinity() call below.
-     */
-    if (!strcmp(hard_str, "-"))
-        hard = NULL;
-    else if (parse_cpurange(hard_str, hard))
-        goto out;
-    /*
-     * Soft affinity is handled similarly. Only difference: we also want
-     * to pass NULL to libxl_set_vcpuaffinity() if it is not specified.
-     */
-    if (argc <= optind+3 || !strcmp(soft_str, "-"))
-        soft = NULL;
-    else if (parse_cpurange(soft_str, soft))
-        goto out;
-
-    if (dryrun_only) {
-        nb_cpu = libxl_get_online_cpus(ctx);
-        if (nb_cpu < 0) {
-            fprintf(stderr, "libxl_get_online_cpus failed.\n");
-            goto out;
-        }
-
-        fprintf(stdout, "cpumap: ");
-        if (hard)
-            print_bitmap(hard->map, nb_cpu, stdout);
-        else
-            fprintf(stdout, "-");
-        if (soft) {
-            fprintf(stdout, " ");
-            print_bitmap(soft->map, nb_cpu, stdout);
-        }
-        fprintf(stdout, "\n");
-
-        if (ferror(stdout) || fflush(stdout)) {
-            perror("stdout");
-            exit(EXIT_FAILURE);
-        }
-
-        rc = EXIT_SUCCESS;
-        goto out;
-    }
-
-    if (force) {
-        if (libxl_set_vcpuaffinity_force(ctx, domid, vcpuid, hard, soft)) {
-            fprintf(stderr, "Could not set affinity for vcpu `%ld'.\n",
-                    vcpuid);
-            goto out;
-        }
-    }
-    else if (vcpuid != -1) {
-        if (libxl_set_vcpuaffinity(ctx, domid, vcpuid, hard, soft)) {
-            fprintf(stderr, "Could not set affinity for vcpu `%ld'.\n",
-                    vcpuid);
-            goto out;
-        }
-    } else {
-        if (!(vcpuinfo = libxl_list_vcpu(ctx, domid, &nb_vcpu, &nb_cpu))) {
-            fprintf(stderr, "libxl_list_vcpu failed.\n");
-            goto out;
-        }
-        if (libxl_set_vcpuaffinity_all(ctx, domid, nb_vcpu, hard, soft))
-            fprintf(stderr, "Could not set affinity.\n");
-        libxl_vcpuinfo_list_free(vcpuinfo, nb_vcpu);
-    }
-
-    rc = EXIT_SUCCESS;
- out:
-    libxl_bitmap_dispose(&cpumap_soft);
-    libxl_bitmap_dispose(&cpumap_hard);
-    return rc;
-}
-
-static int vcpuset(uint32_t domid, const char* nr_vcpus, int check_host)
-{
-    char *endptr;
-    unsigned int max_vcpus, i;
-    libxl_bitmap cpumap;
-    int rc;
-
-    libxl_bitmap_init(&cpumap);
-    max_vcpus = strtoul(nr_vcpus, &endptr, 10);
-    if (nr_vcpus == endptr) {
-        fprintf(stderr, "Error: Invalid argument.\n");
-        return 1;
-    }
-
-    /*
-     * Maximum amount of vCPUS the guest is allowed to set is limited
-     * by the host's amount of pCPUs.
-     */
-    if (check_host) {
-        unsigned int online_vcpus, host_cpu = libxl_get_max_cpus(ctx);
-        libxl_dominfo dominfo;
-
-        if (libxl_domain_info(ctx, &dominfo, domid))
-            return 1;
-
-        online_vcpus = dominfo.vcpu_online;
-        libxl_dominfo_dispose(&dominfo);
-
-        if (max_vcpus > online_vcpus && max_vcpus > host_cpu) {
-            fprintf(stderr, "You are overcommmitting! You have %d physical" \
-                    " CPUs and want %d vCPUs! Aborting, use --ignore-host to" \
-                    " continue\n", host_cpu, max_vcpus);
-            return 1;
-        }
-    }
-    rc = libxl_cpu_bitmap_alloc(ctx, &cpumap, max_vcpus);
-    if (rc) {
-        fprintf(stderr, "libxl_cpu_bitmap_alloc failed, rc: %d\n", rc);
-        return 1;
-    }
-    for (i = 0; i < max_vcpus; i++)
-        libxl_bitmap_set(&cpumap, i);
-
-    rc = libxl_set_vcpuonline(ctx, domid, &cpumap);
-    if (rc == ERROR_DOMAIN_NOTFOUND)
-        fprintf(stderr, "Domain %u does not exist.\n", domid);
-    else if (rc)
-        fprintf(stderr, "libxl_set_vcpuonline failed domid=%u max_vcpus=%d," \
-                " rc: %d\n", domid, max_vcpus, rc);
-
-    libxl_bitmap_dispose(&cpumap);
-    return rc ? 1 : 0;
-}
-
-int main_vcpuset(int argc, char **argv)
-{
-    static struct option opts[] = {
-        {"ignore-host", 0, 0, 'i'},
-        COMMON_LONG_OPTS
-    };
-    int opt, check_host = 1;
-
-    SWITCH_FOREACH_OPT(opt, "i", opts, "vcpu-set", 2) {
-    case 'i':
-        check_host = 0;
-        break;
-    default:
-        break;
-    }
-
-    if (vcpuset(xfind_domain(argv[optind]), argv[optind + 1], check_host))
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
 /* Possibly select a specific piece of `xl info` to print. */
 static const char *info_name;
 static int maybe_printf(const char *fmt, ...) __attribute__((format(printf,1,2)));
diff --git a/tools/xl/xl_vcpu.c b/tools/xl/xl_vcpu.c
new file mode 100644
index 0000000000..4db96e7933
--- /dev/null
+++ b/tools/xl/xl_vcpu.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <stdlib.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+static void print_vcpuinfo(uint32_t tdomid,
+                           const libxl_vcpuinfo *vcpuinfo,
+                           uint32_t nr_cpus)
+{
+    char *domname;
+
+    /*      NAME  ID  VCPU */
+    domname = libxl_domid_to_name(ctx, tdomid);
+    printf("%-32s %5u %5u",
+           domname, tdomid, vcpuinfo->vcpuid);
+    free(domname);
+    if (!vcpuinfo->online) {
+        /*      CPU STA */
+        printf("%5c %3c%cp ", '-', '-', '-');
+    } else {
+        /*      CPU STA */
+        printf("%5u %3c%c- ", vcpuinfo->cpu,
+               vcpuinfo->running ? 'r' : '-',
+               vcpuinfo->blocked ? 'b' : '-');
+    }
+    /*      TIM */
+    printf("%9.1f  ", ((float)vcpuinfo->vcpu_time / 1e9));
+    /* CPU HARD AND SOFT AFFINITY */
+    print_bitmap(vcpuinfo->cpumap.map, nr_cpus, stdout);
+    printf(" / ");
+    print_bitmap(vcpuinfo->cpumap_soft.map, nr_cpus, stdout);
+    printf("\n");
+}
+
+static void print_domain_vcpuinfo(uint32_t domid, uint32_t nr_cpus)
+{
+    libxl_vcpuinfo *vcpuinfo;
+    int i, nb_vcpu, nrcpus;
+
+    vcpuinfo = libxl_list_vcpu(ctx, domid, &nb_vcpu, &nrcpus);
+
+    if (!vcpuinfo)
+        return;
+
+    for (i = 0; i < nb_vcpu; i++) {
+        print_vcpuinfo(domid, &vcpuinfo[i], nr_cpus);
+    }
+
+    libxl_vcpuinfo_list_free(vcpuinfo, nb_vcpu);
+}
+
+static void vcpulist(int argc, char **argv)
+{
+    libxl_dominfo *dominfo;
+    libxl_physinfo physinfo;
+    int i, nb_domain;
+
+    if (libxl_get_physinfo(ctx, &physinfo) != 0) {
+        fprintf(stderr, "libxl_physinfo failed.\n");
+        goto vcpulist_out;
+    }
+
+    printf("%-32s %5s %5s %5s %5s %9s %s\n",
+           "Name", "ID", "VCPU", "CPU", "State", "Time(s)",
+           "Affinity (Hard / Soft)");
+    if (!argc) {
+        if (!(dominfo = libxl_list_domain(ctx, &nb_domain))) {
+            fprintf(stderr, "libxl_list_domain failed.\n");
+            goto vcpulist_out;
+        }
+
+        for (i = 0; i<nb_domain; i++)
+            print_domain_vcpuinfo(dominfo[i].domid, physinfo.nr_cpus);
+
+        libxl_dominfo_list_free(dominfo, nb_domain);
+    } else {
+        for (; argc > 0; ++argv, --argc) {
+            uint32_t domid = xfind_domain(*argv);
+            print_domain_vcpuinfo(domid, physinfo.nr_cpus);
+        }
+    }
+  vcpulist_out:
+    libxl_physinfo_dispose(&physinfo);
+}
+
+int main_vcpulist(int argc, char **argv)
+{
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vcpu-list", 0) {
+        /* No options */
+    }
+
+    vcpulist(argc - optind, argv + optind);
+    return EXIT_SUCCESS;
+}
+
+int main_vcpupin(int argc, char **argv)
+{
+    static struct option opts[] = {
+        {"force", 0, 0, 'f'},
+        COMMON_LONG_OPTS
+    };
+    libxl_vcpuinfo *vcpuinfo;
+    libxl_bitmap cpumap_hard, cpumap_soft;;
+    libxl_bitmap *soft = &cpumap_soft, *hard = &cpumap_hard;
+    uint32_t domid;
+    /*
+     * int would be enough for vcpuid, but we don't want to
+     * mess aroung range checking the return value of strtol().
+     */
+    long vcpuid;
+    const char *vcpu, *hard_str, *soft_str;
+    char *endptr;
+    int opt, nb_cpu, nb_vcpu, rc = EXIT_FAILURE;
+    bool force = false;
+
+    libxl_bitmap_init(&cpumap_hard);
+    libxl_bitmap_init(&cpumap_soft);
+
+    SWITCH_FOREACH_OPT(opt, "f", opts, "vcpu-pin", 3) {
+    case 'f':
+        force = true;
+        break;
+    default:
+        break;
+    }
+
+    domid = xfind_domain(argv[optind]);
+    vcpu = argv[optind+1];
+    hard_str = argv[optind+2];
+    soft_str = (argc > optind+3) ? argv[optind+3] : NULL;
+
+    /* Figure out with which vCPU we are dealing with */
+    vcpuid = strtol(vcpu, &endptr, 10);
+    if (vcpu == endptr || vcpuid < 0) {
+        if (strcmp(vcpu, "all")) {
+            fprintf(stderr, "Error: Invalid argument %s as VCPU.\n", vcpu);
+            goto out;
+        }
+        if (force) {
+            fprintf(stderr, "Error: --force and 'all' as VCPU not allowed.\n");
+            goto out;
+        }
+        vcpuid = -1;
+    }
+
+    if (libxl_cpu_bitmap_alloc(ctx, &cpumap_hard, 0) ||
+        libxl_cpu_bitmap_alloc(ctx, &cpumap_soft, 0))
+        goto out;
+
+    /*
+     * Syntax is: xl vcpu-pin <domid> <vcpu> <hard> <soft>
+     * We want to handle all the following cases ('-' means
+     * "leave it alone"):
+     *  xl vcpu-pin 0 3 3,4
+     *  xl vcpu-pin 0 3 3,4 -
+     *  xl vcpu-pin 0 3 - 6-9
+     *  xl vcpu-pin 0 3 3,4 6-9
+     */
+
+    /*
+     * Hard affinity is always present. However, if it's "-", all we need
+     * is passing a NULL pointer to the libxl_set_vcpuaffinity() call below.
+     */
+    if (!strcmp(hard_str, "-"))
+        hard = NULL;
+    else if (parse_cpurange(hard_str, hard))
+        goto out;
+    /*
+     * Soft affinity is handled similarly. Only difference: we also want
+     * to pass NULL to libxl_set_vcpuaffinity() if it is not specified.
+     */
+    if (argc <= optind+3 || !strcmp(soft_str, "-"))
+        soft = NULL;
+    else if (parse_cpurange(soft_str, soft))
+        goto out;
+
+    if (dryrun_only) {
+        nb_cpu = libxl_get_online_cpus(ctx);
+        if (nb_cpu < 0) {
+            fprintf(stderr, "libxl_get_online_cpus failed.\n");
+            goto out;
+        }
+
+        fprintf(stdout, "cpumap: ");
+        if (hard)
+            print_bitmap(hard->map, nb_cpu, stdout);
+        else
+            fprintf(stdout, "-");
+        if (soft) {
+            fprintf(stdout, " ");
+            print_bitmap(soft->map, nb_cpu, stdout);
+        }
+        fprintf(stdout, "\n");
+
+        if (ferror(stdout) || fflush(stdout)) {
+            perror("stdout");
+            exit(EXIT_FAILURE);
+        }
+
+        rc = EXIT_SUCCESS;
+        goto out;
+    }
+
+    if (force) {
+        if (libxl_set_vcpuaffinity_force(ctx, domid, vcpuid, hard, soft)) {
+            fprintf(stderr, "Could not set affinity for vcpu `%ld'.\n",
+                    vcpuid);
+            goto out;
+        }
+    }
+    else if (vcpuid != -1) {
+        if (libxl_set_vcpuaffinity(ctx, domid, vcpuid, hard, soft)) {
+            fprintf(stderr, "Could not set affinity for vcpu `%ld'.\n",
+                    vcpuid);
+            goto out;
+        }
+    } else {
+        if (!(vcpuinfo = libxl_list_vcpu(ctx, domid, &nb_vcpu, &nb_cpu))) {
+            fprintf(stderr, "libxl_list_vcpu failed.\n");
+            goto out;
+        }
+        if (libxl_set_vcpuaffinity_all(ctx, domid, nb_vcpu, hard, soft))
+            fprintf(stderr, "Could not set affinity.\n");
+        libxl_vcpuinfo_list_free(vcpuinfo, nb_vcpu);
+    }
+
+    rc = EXIT_SUCCESS;
+ out:
+    libxl_bitmap_dispose(&cpumap_soft);
+    libxl_bitmap_dispose(&cpumap_hard);
+    return rc;
+}
+
+static int vcpuset(uint32_t domid, const char* nr_vcpus, int check_host)
+{
+    char *endptr;
+    unsigned int max_vcpus, i;
+    libxl_bitmap cpumap;
+    int rc;
+
+    libxl_bitmap_init(&cpumap);
+    max_vcpus = strtoul(nr_vcpus, &endptr, 10);
+    if (nr_vcpus == endptr) {
+        fprintf(stderr, "Error: Invalid argument.\n");
+        return 1;
+    }
+
+    /*
+     * Maximum amount of vCPUS the guest is allowed to set is limited
+     * by the host's amount of pCPUs.
+     */
+    if (check_host) {
+        unsigned int online_vcpus, host_cpu = libxl_get_max_cpus(ctx);
+        libxl_dominfo dominfo;
+
+        if (libxl_domain_info(ctx, &dominfo, domid))
+            return 1;
+
+        online_vcpus = dominfo.vcpu_online;
+        libxl_dominfo_dispose(&dominfo);
+
+        if (max_vcpus > online_vcpus && max_vcpus > host_cpu) {
+            fprintf(stderr, "You are overcommmitting! You have %d physical" \
+                    " CPUs and want %d vCPUs! Aborting, use --ignore-host to" \
+                    " continue\n", host_cpu, max_vcpus);
+            return 1;
+        }
+    }
+    rc = libxl_cpu_bitmap_alloc(ctx, &cpumap, max_vcpus);
+    if (rc) {
+        fprintf(stderr, "libxl_cpu_bitmap_alloc failed, rc: %d\n", rc);
+        return 1;
+    }
+    for (i = 0; i < max_vcpus; i++)
+        libxl_bitmap_set(&cpumap, i);
+
+    rc = libxl_set_vcpuonline(ctx, domid, &cpumap);
+    if (rc == ERROR_DOMAIN_NOTFOUND)
+        fprintf(stderr, "Domain %u does not exist.\n", domid);
+    else if (rc)
+        fprintf(stderr, "libxl_set_vcpuonline failed domid=%u max_vcpus=%d," \
+                " rc: %d\n", domid, max_vcpus, rc);
+
+    libxl_bitmap_dispose(&cpumap);
+    return rc ? 1 : 0;
+}
+
+int main_vcpuset(int argc, char **argv)
+{
+    static struct option opts[] = {
+        {"ignore-host", 0, 0, 'i'},
+        COMMON_LONG_OPTS
+    };
+    int opt, check_host = 1;
+
+    SWITCH_FOREACH_OPT(opt, "i", opts, "vcpu-set", 2) {
+    case 'i':
+        check_host = 0;
+        break;
+    default:
+        break;
+    }
+
+    if (vcpuset(xfind_domain(argv[optind]), argv[optind + 1], check_host))
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 20/29] xl: split out cd related code
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (18 preceding siblings ...)
  2017-02-24 16:13 ` [PATCH 19/29] xl: split out vcpu " Wei Liu
@ 2017-02-24 16:13 ` Wei Liu
  2017-02-27 15:56   ` Ian Jackson
  2017-02-24 16:13 ` [PATCH 21/29] xl: split out memory " Wei Liu
                   ` (8 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:13 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   2 +-
 tools/xl/xl_cd.c      | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/xl/xl_cmdimpl.c |  80 -----------------------------------
 3 files changed, 115 insertions(+), 81 deletions(-)
 create mode 100644 tools/xl/xl_cd.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index e6e8cef710..89cf9069e0 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -18,7 +18,7 @@ CFLAGS_XL += -Wshadow
 XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
 XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
 XL_OBJS += xl_vtpm.o xl_block.o xl_nic.o xl_usb.o
-XL_OBJS += xl_sched.o xl_pci.o xl_vcpu.o
+XL_OBJS += xl_sched.o xl_pci.o xl_vcpu.o xl_cd.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_cd.c b/tools/xl/xl_cd.c
new file mode 100644
index 0000000000..d99f461c6d
--- /dev/null
+++ b/tools/xl/xl_cd.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+static int cd_insert(uint32_t domid, const char *virtdev, char *phys)
+{
+    libxl_device_disk disk;
+    char *buf = NULL;
+    XLU_Config *config = 0;
+    struct stat b;
+    int r;
+
+    xasprintf(&buf, "vdev=%s,access=r,devtype=cdrom,target=%s",
+              virtdev, phys ? phys : "");
+
+    parse_disk_config(&config, buf, &disk);
+
+    /* ATM the existence of the backing file is not checked for qdisk
+     * in libxl_cdrom_insert() because RAW is used for remote
+     * protocols as well as plain files.  This will ideally be changed
+     * for 4.4, but this work-around fixes the problem of "cd-insert"
+     * returning success for non-existent files. */
+    if (disk.format != LIBXL_DISK_FORMAT_EMPTY
+        && stat(disk.pdev_path, &b)) {
+        fprintf(stderr, "Cannot stat file: %s\n",
+                disk.pdev_path);
+        r = 1;
+        goto out;
+    }
+
+    if (libxl_cdrom_insert(ctx, domid, &disk, NULL)) {
+        r = 1;
+        goto out;
+    }
+
+    r = 0;
+
+out:
+    libxl_device_disk_dispose(&disk);
+    free(buf);
+
+    return r;
+}
+
+int main_cd_eject(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt = 0;
+    const char *virtdev;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "cd-eject", 2) {
+        /* No options */
+    }
+
+    domid = xfind_domain(argv[optind]);
+    virtdev = argv[optind + 1];
+
+    if (cd_insert(domid, virtdev, NULL))
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+int main_cd_insert(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt = 0;
+    const char *virtdev;
+    char *file = NULL; /* modified by cd_insert tokenising it */
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "cd-insert", 3) {
+        /* No options */
+    }
+
+    domid = xfind_domain(argv[optind]);
+    virtdev = argv[optind + 1];
+    file = argv[optind + 2];
+
+    if (cd_insert(domid, virtdev, file))
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index faeac675ad..e15baae861 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -1213,86 +1213,6 @@ int main_memset(int argc, char **argv)
     return set_memory_target(domid, mem);
 }
 
-static int cd_insert(uint32_t domid, const char *virtdev, char *phys)
-{
-    libxl_device_disk disk;
-    char *buf = NULL;
-    XLU_Config *config = 0;
-    struct stat b;
-    int r;
-
-    xasprintf(&buf, "vdev=%s,access=r,devtype=cdrom,target=%s",
-              virtdev, phys ? phys : "");
-
-    parse_disk_config(&config, buf, &disk);
-
-    /* ATM the existence of the backing file is not checked for qdisk
-     * in libxl_cdrom_insert() because RAW is used for remote
-     * protocols as well as plain files.  This will ideally be changed
-     * for 4.4, but this work-around fixes the problem of "cd-insert"
-     * returning success for non-existent files. */
-    if (disk.format != LIBXL_DISK_FORMAT_EMPTY
-        && stat(disk.pdev_path, &b)) {
-        fprintf(stderr, "Cannot stat file: %s\n",
-                disk.pdev_path);
-        r = 1;
-        goto out;
-    }
-
-    if (libxl_cdrom_insert(ctx, domid, &disk, NULL)) {
-        r = 1;
-        goto out;
-    }
-
-    r = 0;
-
-out:
-    libxl_device_disk_dispose(&disk);
-    free(buf);
-
-    return r;
-}
-
-int main_cd_eject(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt = 0;
-    const char *virtdev;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "cd-eject", 2) {
-        /* No options */
-    }
-
-    domid = xfind_domain(argv[optind]);
-    virtdev = argv[optind + 1];
-
-    if (cd_insert(domid, virtdev, NULL))
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
-int main_cd_insert(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt = 0;
-    const char *virtdev;
-    char *file = NULL; /* modified by cd_insert tokenising it */
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "cd-insert", 3) {
-        /* No options */
-    }
-
-    domid = xfind_domain(argv[optind]);
-    virtdev = argv[optind + 1];
-    file = argv[optind + 2];
-
-    if (cd_insert(domid, virtdev, file))
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
-
 int main_console(int argc, char **argv)
 {
     uint32_t domid;
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 21/29] xl: split out memory related code
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (19 preceding siblings ...)
  2017-02-24 16:13 ` [PATCH 20/29] xl: split out cd " Wei Liu
@ 2017-02-24 16:13 ` Wei Liu
  2017-02-27 16:01   ` Ian Jackson
  2017-02-24 16:13 ` [PATCH 22/29] xl: split out psr " Wei Liu
                   ` (7 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:13 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   2 +-
 tools/xl/xl_cmdimpl.c | 136 ----------------------------------------
 tools/xl/xl_mem.c     | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 168 insertions(+), 137 deletions(-)
 create mode 100644 tools/xl/xl_mem.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index 89cf9069e0..964da8e705 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -18,7 +18,7 @@ CFLAGS_XL += -Wshadow
 XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
 XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
 XL_OBJS += xl_vtpm.o xl_block.o xl_nic.o xl_usb.o
-XL_OBJS += xl_sched.o xl_pci.o xl_vcpu.o xl_cd.o
+XL_OBJS += xl_sched.o xl_pci.o xl_vcpu.o xl_cd.o xl_mem.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index e15baae861..35d81417ec 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -1145,74 +1145,6 @@ void help(const char *command)
     }
 }
 
-static int set_memory_max(uint32_t domid, const char *mem)
-{
-    int64_t memorykb;
-
-    memorykb = parse_mem_size_kb(mem);
-    if (memorykb == -1) {
-        fprintf(stderr, "invalid memory size: %s\n", mem);
-        return EXIT_FAILURE;
-    }
-
-    if (libxl_domain_setmaxmem(ctx, domid, memorykb)) {
-        fprintf(stderr, "cannot set domid %u static max memory to : %s\n", domid, mem);
-        return EXIT_FAILURE;
-    }
-
-    return EXIT_SUCCESS;
-}
-
-int main_memmax(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt = 0;
-    char *mem;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "mem-max", 2) {
-        /* No options */
-    }
-
-    domid = xfind_domain(argv[optind]);
-    mem = argv[optind + 1];
-
-    return set_memory_max(domid, mem);
-}
-
-static int set_memory_target(uint32_t domid, const char *mem)
-{
-    int64_t memorykb;
-
-    memorykb = parse_mem_size_kb(mem);
-    if (memorykb == -1)  {
-        fprintf(stderr, "invalid memory size: %s\n", mem);
-        return EXIT_FAILURE;
-    }
-
-    if (libxl_set_memory_target(ctx, domid, memorykb, 0, /* enforce */ 1)) {
-        fprintf(stderr, "cannot set domid %u dynamic max memory to : %s\n", domid, mem);
-        return EXIT_FAILURE;
-    }
-
-    return EXIT_SUCCESS;
-}
-
-int main_memset(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt = 0;
-    const char *mem;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "mem-set", 2) {
-        /* No options */
-    }
-
-    domid = xfind_domain(argv[optind]);
-    mem = argv[optind + 1];
-
-    return set_memory_target(domid, mem);
-}
-
 int main_console(int argc, char **argv)
 {
     uint32_t domid;
@@ -3056,74 +2988,6 @@ int main_info(int argc, char **argv)
     return 0;
 }
 
-static void sharing(const libxl_dominfo *info, int nb_domain)
-{
-    int i;
-
-    printf("Name                                        ID   Mem Shared\n");
-
-    for (i = 0; i < nb_domain; i++) {
-        char *domname;
-        unsigned shutdown_reason;
-        domname = libxl_domid_to_name(ctx, info[i].domid);
-        shutdown_reason = info[i].shutdown ? info[i].shutdown_reason : 0;
-        printf("%-40s %5d %5lu  %5lu\n",
-                domname,
-                info[i].domid,
-                (unsigned long) ((info[i].current_memkb +
-                    info[i].outstanding_memkb) / 1024),
-                (unsigned long) (info[i].shared_memkb / 1024));
-        free(domname);
-    }
-}
-
-int main_sharing(int argc, char **argv)
-{
-    int opt = 0;
-    libxl_dominfo info_buf;
-    libxl_dominfo *info, *info_free = NULL;
-    int nb_domain, rc;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "sharing", 0) {
-        /* No options */
-    }
-
-    if (optind >= argc) {
-        info = libxl_list_domain(ctx, &nb_domain);
-        if (!info) {
-            fprintf(stderr, "libxl_list_domain failed.\n");
-            return EXIT_FAILURE;
-        }
-        info_free = info;
-    } else if (optind == argc-1) {
-        uint32_t domid = xfind_domain(argv[optind]);
-        rc = libxl_domain_info(ctx, &info_buf, domid);
-        if (rc == ERROR_DOMAIN_NOTFOUND) {
-            fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
-                argv[optind]);
-            return EXIT_FAILURE;
-        }
-        if (rc) {
-            fprintf(stderr, "libxl_domain_info failed (code %d).\n", rc);
-            return EXIT_FAILURE;
-        }
-        info = &info_buf;
-        nb_domain = 1;
-    } else {
-        help("sharing");
-        return EXIT_FAILURE;
-    }
-
-    sharing(info, nb_domain);
-
-    if (info_free)
-        libxl_dominfo_list_free(info_free, nb_domain);
-    else
-        libxl_dominfo_dispose(info);
-
-    return EXIT_SUCCESS;
-}
-
 int main_domid(int argc, char **argv)
 {
     uint32_t domid;
diff --git a/tools/xl/xl_mem.c b/tools/xl/xl_mem.c
new file mode 100644
index 0000000000..736d1f8f34
--- /dev/null
+++ b/tools/xl/xl_mem.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <stdlib.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+static int set_memory_max(uint32_t domid, const char *mem)
+{
+    int64_t memorykb;
+
+    memorykb = parse_mem_size_kb(mem);
+    if (memorykb == -1) {
+        fprintf(stderr, "invalid memory size: %s\n", mem);
+        return EXIT_FAILURE;
+    }
+
+    if (libxl_domain_setmaxmem(ctx, domid, memorykb)) {
+        fprintf(stderr, "cannot set domid %u static max memory to : %s\n", domid, mem);
+        return EXIT_FAILURE;
+    }
+
+    return EXIT_SUCCESS;
+}
+
+int main_memmax(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt = 0;
+    char *mem;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "mem-max", 2) {
+        /* No options */
+    }
+
+    domid = xfind_domain(argv[optind]);
+    mem = argv[optind + 1];
+
+    return set_memory_max(domid, mem);
+}
+
+static int set_memory_target(uint32_t domid, const char *mem)
+{
+    int64_t memorykb;
+
+    memorykb = parse_mem_size_kb(mem);
+    if (memorykb == -1)  {
+        fprintf(stderr, "invalid memory size: %s\n", mem);
+        return EXIT_FAILURE;
+    }
+
+    if (libxl_set_memory_target(ctx, domid, memorykb, 0, /* enforce */ 1)) {
+        fprintf(stderr, "cannot set domid %u dynamic max memory to : %s\n", domid, mem);
+        return EXIT_FAILURE;
+    }
+
+    return EXIT_SUCCESS;
+}
+
+int main_memset(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt = 0;
+    const char *mem;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "mem-set", 2) {
+        /* No options */
+    }
+
+    domid = xfind_domain(argv[optind]);
+    mem = argv[optind + 1];
+
+    return set_memory_target(domid, mem);
+}
+
+static void sharing(const libxl_dominfo *info, int nb_domain)
+{
+    int i;
+
+    printf("Name                                        ID   Mem Shared\n");
+
+    for (i = 0; i < nb_domain; i++) {
+        char *domname;
+        unsigned shutdown_reason;
+        domname = libxl_domid_to_name(ctx, info[i].domid);
+        shutdown_reason = info[i].shutdown ? info[i].shutdown_reason : 0;
+        printf("%-40s %5d %5lu  %5lu\n",
+                domname,
+                info[i].domid,
+                (unsigned long) ((info[i].current_memkb +
+                    info[i].outstanding_memkb) / 1024),
+                (unsigned long) (info[i].shared_memkb / 1024));
+        free(domname);
+    }
+}
+
+int main_sharing(int argc, char **argv)
+{
+    int opt = 0;
+    libxl_dominfo info_buf;
+    libxl_dominfo *info, *info_free = NULL;
+    int nb_domain, rc;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "sharing", 0) {
+        /* No options */
+    }
+
+    if (optind >= argc) {
+        info = libxl_list_domain(ctx, &nb_domain);
+        if (!info) {
+            fprintf(stderr, "libxl_list_domain failed.\n");
+            return EXIT_FAILURE;
+        }
+        info_free = info;
+    } else if (optind == argc-1) {
+        uint32_t domid = xfind_domain(argv[optind]);
+        rc = libxl_domain_info(ctx, &info_buf, domid);
+        if (rc == ERROR_DOMAIN_NOTFOUND) {
+            fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
+                argv[optind]);
+            return EXIT_FAILURE;
+        }
+        if (rc) {
+            fprintf(stderr, "libxl_domain_info failed (code %d).\n", rc);
+            return EXIT_FAILURE;
+        }
+        info = &info_buf;
+        nb_domain = 1;
+    } else {
+        help("sharing");
+        return EXIT_FAILURE;
+    }
+
+    sharing(info, nb_domain);
+
+    if (info_free)
+        libxl_dominfo_list_free(info_free, nb_domain);
+    else
+        libxl_dominfo_dispose(info);
+
+    return EXIT_SUCCESS;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 22/29] xl: split out psr related code
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (20 preceding siblings ...)
  2017-02-24 16:13 ` [PATCH 21/29] xl: split out memory " Wei Liu
@ 2017-02-24 16:13 ` Wei Liu
  2017-02-27 15:55   ` Ian Jackson
  2017-02-24 16:13 ` [PATCH 23/29] xl: split out functions to print out information Wei Liu
                   ` (6 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:13 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   1 +
 tools/xl/xl_cmdimpl.c | 533 -----------------------------------------------
 tools/xl/xl_psr.c     | 567 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 568 insertions(+), 533 deletions(-)
 create mode 100644 tools/xl/xl_psr.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index 964da8e705..fdb64fed1d 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -19,6 +19,7 @@ XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
 XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
 XL_OBJS += xl_vtpm.o xl_block.o xl_nic.o xl_usb.o
 XL_OBJS += xl_sched.o xl_pci.o xl_vcpu.o xl_cd.o xl_mem.o
+XL_OBJS += xl_psr.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index 35d81417ec..f6942ffbe8 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -3619,539 +3619,6 @@ out:
     return ret;
 }
 
-#ifdef LIBXL_HAVE_PSR_CMT
-static int psr_cmt_hwinfo(void)
-{
-    int rc;
-    int enabled;
-    uint32_t total_rmid;
-
-    printf("Cache Monitoring Technology (CMT):\n");
-
-    enabled = libxl_psr_cmt_enabled(ctx);
-    printf("%-16s: %s\n", "Enabled", enabled ? "1" : "0");
-    if (!enabled)
-        return 0;
-
-    rc = libxl_psr_cmt_get_total_rmid(ctx, &total_rmid);
-    if (rc) {
-        fprintf(stderr, "Failed to get max RMID value\n");
-        return rc;
-    }
-    printf("%-16s: %u\n", "Total RMID", total_rmid);
-
-    printf("Supported monitor types:\n");
-    if (libxl_psr_cmt_type_supported(ctx, LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY))
-        printf("cache-occupancy\n");
-    if (libxl_psr_cmt_type_supported(ctx, LIBXL_PSR_CMT_TYPE_TOTAL_MEM_COUNT))
-        printf("total-mem-bandwidth\n");
-    if (libxl_psr_cmt_type_supported(ctx, LIBXL_PSR_CMT_TYPE_LOCAL_MEM_COUNT))
-        printf("local-mem-bandwidth\n");
-
-    return rc;
-}
-
-#define MBM_SAMPLE_RETRY_MAX 4
-static int psr_cmt_get_mem_bandwidth(uint32_t domid,
-                                     libxl_psr_cmt_type type,
-                                     uint32_t socketid,
-                                     uint64_t *bandwidth_r)
-{
-    uint64_t sample1, sample2;
-    uint64_t tsc1, tsc2;
-    int retry_attempts = 0;
-    int rc;
-
-    while (1) {
-        rc = libxl_psr_cmt_get_sample(ctx, domid, type, socketid,
-                                      &sample1, &tsc1);
-        if (rc < 0)
-            return rc;
-
-        usleep(10000);
-
-        rc = libxl_psr_cmt_get_sample(ctx, domid, type, socketid,
-                                      &sample2, &tsc2);
-        if (rc < 0)
-            return rc;
-
-        if (tsc2 <= tsc1)
-            return -1;
-
-        /*
-         * Hardware guarantees at most 1 overflow can happen if the duration
-         * between two samples is less than 1 second. Note that tsc returned
-         * from hypervisor is already-scaled time(ns).
-         */
-        if (tsc2 - tsc1 < 1000000000 && sample2 >= sample1)
-            break;
-
-        if (retry_attempts < MBM_SAMPLE_RETRY_MAX) {
-            retry_attempts++;
-        } else {
-            fprintf(stderr, "event counter overflowed\n");
-            return -1;
-        }
-    }
-
-    *bandwidth_r = (sample2 - sample1) * 1000000000 / (tsc2 - tsc1) / 1024;
-    return 0;
-}
-
-static void psr_cmt_print_domain_info(libxl_dominfo *dominfo,
-                                      libxl_psr_cmt_type type,
-                                      libxl_bitmap *socketmap)
-{
-    char *domain_name;
-    uint32_t socketid;
-    uint64_t monitor_data;
-
-    if (!libxl_psr_cmt_domain_attached(ctx, dominfo->domid))
-        return;
-
-    domain_name = libxl_domid_to_name(ctx, dominfo->domid);
-    printf("%-40s %5d", domain_name, dominfo->domid);
-    free(domain_name);
-
-    libxl_for_each_set_bit(socketid, *socketmap) {
-        switch (type) {
-        case LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY:
-            if (!libxl_psr_cmt_get_sample(ctx, dominfo->domid, type, socketid,
-                                          &monitor_data, NULL))
-                printf("%13"PRIu64" KB", monitor_data / 1024);
-            break;
-        case LIBXL_PSR_CMT_TYPE_TOTAL_MEM_COUNT:
-        case LIBXL_PSR_CMT_TYPE_LOCAL_MEM_COUNT:
-            if (!psr_cmt_get_mem_bandwidth(dominfo->domid, type, socketid,
-                                           &monitor_data))
-                printf("%11"PRIu64" KB/s", monitor_data);
-            break;
-        default:
-            return;
-        }
-    }
-
-    printf("\n");
-}
-
-static int psr_cmt_show(libxl_psr_cmt_type type, uint32_t domid)
-{
-    uint32_t i, socketid, total_rmid;
-    uint32_t l3_cache_size;
-    libxl_bitmap socketmap;
-    int rc, nr_domains;
-
-    if (!libxl_psr_cmt_enabled(ctx)) {
-        fprintf(stderr, "CMT is disabled in the system\n");
-        return -1;
-    }
-
-    if (!libxl_psr_cmt_type_supported(ctx, type)) {
-        fprintf(stderr, "Monitor type '%s' is not supported in the system\n",
-                libxl_psr_cmt_type_to_string(type));
-        return -1;
-    }
-
-    libxl_bitmap_init(&socketmap);
-    libxl_socket_bitmap_alloc(ctx, &socketmap, 0);
-    rc = libxl_get_online_socketmap(ctx, &socketmap);
-    if (rc < 0) {
-        fprintf(stderr, "Failed getting available sockets, rc: %d\n", rc);
-        goto out;
-    }
-
-    rc = libxl_psr_cmt_get_total_rmid(ctx, &total_rmid);
-    if (rc < 0) {
-        fprintf(stderr, "Failed to get max RMID value\n");
-        goto out;
-    }
-
-    printf("Total RMID: %d\n", total_rmid);
-
-    /* Header */
-    printf("%-40s %5s", "Name", "ID");
-    libxl_for_each_set_bit(socketid, socketmap)
-        printf("%14s %d", "Socket", socketid);
-    printf("\n");
-
-    if (type == LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY) {
-            /* Total L3 cache size */
-            printf("%-46s", "Total L3 Cache Size");
-            libxl_for_each_set_bit(socketid, socketmap) {
-                rc = libxl_psr_cmt_get_l3_cache_size(ctx, socketid,
-                                                     &l3_cache_size);
-                if (rc < 0) {
-                    fprintf(stderr,
-                            "Failed to get system l3 cache size for socket:%d\n",
-                            socketid);
-                    goto out;
-                }
-                printf("%13u KB", l3_cache_size);
-            }
-            printf("\n");
-    }
-
-    /* Each domain */
-    if (domid != INVALID_DOMID) {
-        libxl_dominfo dominfo;
-
-        libxl_dominfo_init(&dominfo);
-        if (libxl_domain_info(ctx, &dominfo, domid)) {
-            fprintf(stderr, "Failed to get domain info for %d\n", domid);
-            rc = -1;
-            goto out;
-        }
-        psr_cmt_print_domain_info(&dominfo, type, &socketmap);
-        libxl_dominfo_dispose(&dominfo);
-    }
-    else
-    {
-        libxl_dominfo *list;
-        if (!(list = libxl_list_domain(ctx, &nr_domains))) {
-            fprintf(stderr, "Failed to get domain info for domain list.\n");
-            rc = -1;
-            goto out;
-        }
-        for (i = 0; i < nr_domains; i++)
-            psr_cmt_print_domain_info(list + i, type, &socketmap);
-        libxl_dominfo_list_free(list, nr_domains);
-    }
-
-out:
-    libxl_bitmap_dispose(&socketmap);
-    return rc;
-}
-
-int main_psr_cmt_attach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt, ret = 0;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cmt-attach", 1) {
-        /* No options */
-    }
-
-    domid = xfind_domain(argv[optind]);
-    ret = libxl_psr_cmt_attach(ctx, domid);
-
-    return ret;
-}
-
-int main_psr_cmt_detach(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt, ret = 0;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cmt-detach", 1) {
-        /* No options */
-    }
-
-    domid = xfind_domain(argv[optind]);
-    ret = libxl_psr_cmt_detach(ctx, domid);
-
-    return ret;
-}
-
-int main_psr_cmt_show(int argc, char **argv)
-{
-    int opt, ret = 0;
-    uint32_t domid;
-    libxl_psr_cmt_type type;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cmt-show", 1) {
-        /* No options */
-    }
-
-    if (!strcmp(argv[optind], "cache-occupancy"))
-        type = LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY;
-    else if (!strcmp(argv[optind], "total-mem-bandwidth"))
-        type = LIBXL_PSR_CMT_TYPE_TOTAL_MEM_COUNT;
-    else if (!strcmp(argv[optind], "local-mem-bandwidth"))
-        type = LIBXL_PSR_CMT_TYPE_LOCAL_MEM_COUNT;
-    else {
-        help("psr-cmt-show");
-        return 2;
-    }
-
-    if (optind + 1 >= argc)
-        domid = INVALID_DOMID;
-    else if (optind + 1 == argc - 1)
-        domid = xfind_domain(argv[optind + 1]);
-    else {
-        help("psr-cmt-show");
-        return 2;
-    }
-
-    ret = psr_cmt_show(type, domid);
-
-    return ret;
-}
-#endif
-
-#ifdef LIBXL_HAVE_PSR_CAT
-static int psr_cat_hwinfo(void)
-{
-    int rc;
-    int i, nr;
-    uint32_t l3_cache_size;
-    libxl_psr_cat_info *info;
-
-    printf("Cache Allocation Technology (CAT):\n");
-
-    rc = libxl_psr_cat_get_l3_info(ctx, &info, &nr);
-    if (rc) {
-        fprintf(stderr, "Failed to get cat info\n");
-        return rc;
-    }
-
-    for (i = 0; i < nr; i++) {
-        rc = libxl_psr_cmt_get_l3_cache_size(ctx, info[i].id, &l3_cache_size);
-        if (rc) {
-            fprintf(stderr, "Failed to get l3 cache size for socket:%d\n",
-                    info[i].id);
-            goto out;
-        }
-        printf("%-16s: %u\n", "Socket ID", info[i].id);
-        printf("%-16s: %uKB\n", "L3 Cache", l3_cache_size);
-        printf("%-16s: %s\n", "CDP Status",
-               info[i].cdp_enabled ? "Enabled" : "Disabled");
-        printf("%-16s: %u\n", "Maximum COS", info[i].cos_max);
-        printf("%-16s: %u\n", "CBM length", info[i].cbm_len);
-        printf("%-16s: %#llx\n", "Default CBM",
-               (1ull << info[i].cbm_len) - 1);
-    }
-
-out:
-    libxl_psr_cat_info_list_free(info, nr);
-    return rc;
-}
-
-static void psr_cat_print_one_domain_cbm_type(uint32_t domid, uint32_t socketid,
-                                              libxl_psr_cbm_type type)
-{
-    uint64_t cbm;
-
-    if (!libxl_psr_cat_get_cbm(ctx, domid, type, socketid, &cbm))
-        printf("%#16"PRIx64, cbm);
-    else
-        printf("%16s", "error");
-}
-
-static void psr_cat_print_one_domain_cbm(uint32_t domid, uint32_t socketid,
-                                         bool cdp_enabled)
-{
-    char *domain_name;
-
-    domain_name = libxl_domid_to_name(ctx, domid);
-    printf("%5d%25s", domid, domain_name);
-    free(domain_name);
-
-    if (!cdp_enabled) {
-        psr_cat_print_one_domain_cbm_type(domid, socketid,
-                                          LIBXL_PSR_CBM_TYPE_L3_CBM);
-    } else {
-        psr_cat_print_one_domain_cbm_type(domid, socketid,
-                                          LIBXL_PSR_CBM_TYPE_L3_CBM_CODE);
-        psr_cat_print_one_domain_cbm_type(domid, socketid,
-                                          LIBXL_PSR_CBM_TYPE_L3_CBM_DATA);
-    }
-
-    printf("\n");
-}
-
-static int psr_cat_print_domain_cbm(uint32_t domid, uint32_t socketid,
-                                    bool cdp_enabled)
-{
-    int i, nr_domains;
-    libxl_dominfo *list;
-
-    if (domid != INVALID_DOMID) {
-        psr_cat_print_one_domain_cbm(domid, socketid, cdp_enabled);
-        return 0;
-    }
-
-    if (!(list = libxl_list_domain(ctx, &nr_domains))) {
-        fprintf(stderr, "Failed to get domain list for cbm display\n");
-        return -1;
-    }
-
-    for (i = 0; i < nr_domains; i++)
-        psr_cat_print_one_domain_cbm(list[i].domid, socketid, cdp_enabled);
-    libxl_dominfo_list_free(list, nr_domains);
-
-    return 0;
-}
-
-static int psr_cat_print_socket(uint32_t domid, libxl_psr_cat_info *info)
-{
-    int rc;
-    uint32_t l3_cache_size;
-
-    rc = libxl_psr_cmt_get_l3_cache_size(ctx, info->id, &l3_cache_size);
-    if (rc) {
-        fprintf(stderr, "Failed to get l3 cache size for socket:%d\n",
-                info->id);
-        return -1;
-    }
-
-    printf("%-16s: %u\n", "Socket ID", info->id);
-    printf("%-16s: %uKB\n", "L3 Cache", l3_cache_size);
-    printf("%-16s: %#llx\n", "Default CBM", (1ull << info->cbm_len) - 1);
-    if (info->cdp_enabled)
-        printf("%5s%25s%16s%16s\n", "ID", "NAME", "CBM (code)", "CBM (data)");
-    else
-        printf("%5s%25s%16s\n", "ID", "NAME", "CBM");
-
-    return psr_cat_print_domain_cbm(domid, info->id, info->cdp_enabled);
-}
-
-static int psr_cat_show(uint32_t domid)
-{
-    int i, nr;
-    int rc;
-    libxl_psr_cat_info *info;
-
-    rc = libxl_psr_cat_get_l3_info(ctx, &info, &nr);
-    if (rc) {
-        fprintf(stderr, "Failed to get cat info\n");
-        return rc;
-    }
-
-    for (i = 0; i < nr; i++) {
-        rc = psr_cat_print_socket(domid, info + i);
-        if (rc)
-            goto out;
-    }
-
-out:
-    libxl_psr_cat_info_list_free(info, nr);
-    return rc;
-}
-
-int main_psr_cat_cbm_set(int argc, char **argv)
-{
-    uint32_t domid;
-    libxl_psr_cbm_type type;
-    uint64_t cbm;
-    int ret, opt = 0;
-    int opt_data = 0, opt_code = 0;
-    libxl_bitmap target_map;
-    char *value;
-    libxl_string_list socket_list;
-    unsigned long start, end;
-    int i, j, len;
-
-    static struct option opts[] = {
-        {"socket", 1, 0, 's'},
-        {"data", 0, 0, 'd'},
-        {"code", 0, 0, 'c'},
-        COMMON_LONG_OPTS
-    };
-
-    libxl_socket_bitmap_alloc(ctx, &target_map, 0);
-    libxl_bitmap_set_none(&target_map);
-
-    SWITCH_FOREACH_OPT(opt, "s:cd", opts, "psr-cat-cbm-set", 2) {
-    case 's':
-        trim(isspace, optarg, &value);
-        split_string_into_string_list(value, ",", &socket_list);
-        len = libxl_string_list_length(&socket_list);
-        for (i = 0; i < len; i++) {
-            parse_range(socket_list[i], &start, &end);
-            for (j = start; j <= end; j++)
-                libxl_bitmap_set(&target_map, j);
-        }
-
-        libxl_string_list_dispose(&socket_list);
-        free(value);
-        break;
-    case 'd':
-        opt_data = 1;
-        break;
-    case 'c':
-        opt_code = 1;
-        break;
-    }
-
-    if (opt_data && opt_code) {
-        fprintf(stderr, "Cannot handle -c and -d at the same time\n");
-        return -1;
-    } else if (opt_data) {
-        type = LIBXL_PSR_CBM_TYPE_L3_CBM_DATA;
-    } else if (opt_code) {
-        type = LIBXL_PSR_CBM_TYPE_L3_CBM_CODE;
-    } else {
-        type = LIBXL_PSR_CBM_TYPE_L3_CBM;
-    }
-
-    if (libxl_bitmap_is_empty(&target_map))
-        libxl_bitmap_set_any(&target_map);
-
-    if (argc != optind + 2) {
-        help("psr-cat-cbm-set");
-        return 2;
-    }
-
-    domid = xfind_domain(argv[optind]);
-    cbm = strtoll(argv[optind + 1], NULL , 0);
-
-    ret = libxl_psr_cat_set_cbm(ctx, domid, type, &target_map, cbm);
-
-    libxl_bitmap_dispose(&target_map);
-    return ret;
-}
-
-int main_psr_cat_show(int argc, char **argv)
-{
-    int opt;
-    uint32_t domid;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cat-show", 0) {
-        /* No options */
-    }
-
-    if (optind >= argc)
-        domid = INVALID_DOMID;
-    else if (optind == argc - 1)
-        domid = xfind_domain(argv[optind]);
-    else {
-        help("psr-cat-show");
-        return 2;
-    }
-
-    return psr_cat_show(domid);
-}
-
-int main_psr_hwinfo(int argc, char **argv)
-{
-    int opt, ret = 0;
-    bool all = true, cmt = false, cat = false;
-    static struct option opts[] = {
-        {"cmt", 0, 0, 'm'},
-        {"cat", 0, 0, 'a'},
-        COMMON_LONG_OPTS
-    };
-
-    SWITCH_FOREACH_OPT(opt, "ma", opts, "psr-hwinfo", 0) {
-    case 'm':
-        all = false; cmt = true;
-        break;
-    case 'a':
-        all = false; cat = true;
-        break;
-    }
-
-    if (!ret && (all || cmt))
-        ret = psr_cmt_hwinfo();
-
-    if (!ret && (all || cat))
-        ret = psr_cat_hwinfo();
-
-    return ret;
-}
-
-#endif
-
 int main_qemu_monitor_command(int argc, char **argv)
 {
     int opt;
diff --git a/tools/xl/xl_psr.c b/tools/xl/xl_psr.c
new file mode 100644
index 0000000000..2985622f00
--- /dev/null
+++ b/tools/xl/xl_psr.c
@@ -0,0 +1,567 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+#ifdef LIBXL_HAVE_PSR_CMT
+static int psr_cmt_hwinfo(void)
+{
+    int rc;
+    int enabled;
+    uint32_t total_rmid;
+
+    printf("Cache Monitoring Technology (CMT):\n");
+
+    enabled = libxl_psr_cmt_enabled(ctx);
+    printf("%-16s: %s\n", "Enabled", enabled ? "1" : "0");
+    if (!enabled)
+        return 0;
+
+    rc = libxl_psr_cmt_get_total_rmid(ctx, &total_rmid);
+    if (rc) {
+        fprintf(stderr, "Failed to get max RMID value\n");
+        return rc;
+    }
+    printf("%-16s: %u\n", "Total RMID", total_rmid);
+
+    printf("Supported monitor types:\n");
+    if (libxl_psr_cmt_type_supported(ctx, LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY))
+        printf("cache-occupancy\n");
+    if (libxl_psr_cmt_type_supported(ctx, LIBXL_PSR_CMT_TYPE_TOTAL_MEM_COUNT))
+        printf("total-mem-bandwidth\n");
+    if (libxl_psr_cmt_type_supported(ctx, LIBXL_PSR_CMT_TYPE_LOCAL_MEM_COUNT))
+        printf("local-mem-bandwidth\n");
+
+    return rc;
+}
+
+#define MBM_SAMPLE_RETRY_MAX 4
+static int psr_cmt_get_mem_bandwidth(uint32_t domid,
+                                     libxl_psr_cmt_type type,
+                                     uint32_t socketid,
+                                     uint64_t *bandwidth_r)
+{
+    uint64_t sample1, sample2;
+    uint64_t tsc1, tsc2;
+    int retry_attempts = 0;
+    int rc;
+
+    while (1) {
+        rc = libxl_psr_cmt_get_sample(ctx, domid, type, socketid,
+                                      &sample1, &tsc1);
+        if (rc < 0)
+            return rc;
+
+        usleep(10000);
+
+        rc = libxl_psr_cmt_get_sample(ctx, domid, type, socketid,
+                                      &sample2, &tsc2);
+        if (rc < 0)
+            return rc;
+
+        if (tsc2 <= tsc1)
+            return -1;
+
+        /*
+         * Hardware guarantees at most 1 overflow can happen if the duration
+         * between two samples is less than 1 second. Note that tsc returned
+         * from hypervisor is already-scaled time(ns).
+         */
+        if (tsc2 - tsc1 < 1000000000 && sample2 >= sample1)
+            break;
+
+        if (retry_attempts < MBM_SAMPLE_RETRY_MAX) {
+            retry_attempts++;
+        } else {
+            fprintf(stderr, "event counter overflowed\n");
+            return -1;
+        }
+    }
+
+    *bandwidth_r = (sample2 - sample1) * 1000000000 / (tsc2 - tsc1) / 1024;
+    return 0;
+}
+
+static void psr_cmt_print_domain_info(libxl_dominfo *dominfo,
+                                      libxl_psr_cmt_type type,
+                                      libxl_bitmap *socketmap)
+{
+    char *domain_name;
+    uint32_t socketid;
+    uint64_t monitor_data;
+
+    if (!libxl_psr_cmt_domain_attached(ctx, dominfo->domid))
+        return;
+
+    domain_name = libxl_domid_to_name(ctx, dominfo->domid);
+    printf("%-40s %5d", domain_name, dominfo->domid);
+    free(domain_name);
+
+    libxl_for_each_set_bit(socketid, *socketmap) {
+        switch (type) {
+        case LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY:
+            if (!libxl_psr_cmt_get_sample(ctx, dominfo->domid, type, socketid,
+                                          &monitor_data, NULL))
+                printf("%13"PRIu64" KB", monitor_data / 1024);
+            break;
+        case LIBXL_PSR_CMT_TYPE_TOTAL_MEM_COUNT:
+        case LIBXL_PSR_CMT_TYPE_LOCAL_MEM_COUNT:
+            if (!psr_cmt_get_mem_bandwidth(dominfo->domid, type, socketid,
+                                           &monitor_data))
+                printf("%11"PRIu64" KB/s", monitor_data);
+            break;
+        default:
+            return;
+        }
+    }
+
+    printf("\n");
+}
+
+static int psr_cmt_show(libxl_psr_cmt_type type, uint32_t domid)
+{
+    uint32_t i, socketid, total_rmid;
+    uint32_t l3_cache_size;
+    libxl_bitmap socketmap;
+    int rc, nr_domains;
+
+    if (!libxl_psr_cmt_enabled(ctx)) {
+        fprintf(stderr, "CMT is disabled in the system\n");
+        return -1;
+    }
+
+    if (!libxl_psr_cmt_type_supported(ctx, type)) {
+        fprintf(stderr, "Monitor type '%s' is not supported in the system\n",
+                libxl_psr_cmt_type_to_string(type));
+        return -1;
+    }
+
+    libxl_bitmap_init(&socketmap);
+    libxl_socket_bitmap_alloc(ctx, &socketmap, 0);
+    rc = libxl_get_online_socketmap(ctx, &socketmap);
+    if (rc < 0) {
+        fprintf(stderr, "Failed getting available sockets, rc: %d\n", rc);
+        goto out;
+    }
+
+    rc = libxl_psr_cmt_get_total_rmid(ctx, &total_rmid);
+    if (rc < 0) {
+        fprintf(stderr, "Failed to get max RMID value\n");
+        goto out;
+    }
+
+    printf("Total RMID: %d\n", total_rmid);
+
+    /* Header */
+    printf("%-40s %5s", "Name", "ID");
+    libxl_for_each_set_bit(socketid, socketmap)
+        printf("%14s %d", "Socket", socketid);
+    printf("\n");
+
+    if (type == LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY) {
+            /* Total L3 cache size */
+            printf("%-46s", "Total L3 Cache Size");
+            libxl_for_each_set_bit(socketid, socketmap) {
+                rc = libxl_psr_cmt_get_l3_cache_size(ctx, socketid,
+                                                     &l3_cache_size);
+                if (rc < 0) {
+                    fprintf(stderr,
+                            "Failed to get system l3 cache size for socket:%d\n",
+                            socketid);
+                    goto out;
+                }
+                printf("%13u KB", l3_cache_size);
+            }
+            printf("\n");
+    }
+
+    /* Each domain */
+    if (domid != INVALID_DOMID) {
+        libxl_dominfo dominfo;
+
+        libxl_dominfo_init(&dominfo);
+        if (libxl_domain_info(ctx, &dominfo, domid)) {
+            fprintf(stderr, "Failed to get domain info for %d\n", domid);
+            rc = -1;
+            goto out;
+        }
+        psr_cmt_print_domain_info(&dominfo, type, &socketmap);
+        libxl_dominfo_dispose(&dominfo);
+    }
+    else
+    {
+        libxl_dominfo *list;
+        if (!(list = libxl_list_domain(ctx, &nr_domains))) {
+            fprintf(stderr, "Failed to get domain info for domain list.\n");
+            rc = -1;
+            goto out;
+        }
+        for (i = 0; i < nr_domains; i++)
+            psr_cmt_print_domain_info(list + i, type, &socketmap);
+        libxl_dominfo_list_free(list, nr_domains);
+    }
+
+out:
+    libxl_bitmap_dispose(&socketmap);
+    return rc;
+}
+
+int main_psr_cmt_attach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, ret = 0;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cmt-attach", 1) {
+        /* No options */
+    }
+
+    domid = xfind_domain(argv[optind]);
+    ret = libxl_psr_cmt_attach(ctx, domid);
+
+    return ret;
+}
+
+int main_psr_cmt_detach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, ret = 0;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cmt-detach", 1) {
+        /* No options */
+    }
+
+    domid = xfind_domain(argv[optind]);
+    ret = libxl_psr_cmt_detach(ctx, domid);
+
+    return ret;
+}
+
+int main_psr_cmt_show(int argc, char **argv)
+{
+    int opt, ret = 0;
+    uint32_t domid;
+    libxl_psr_cmt_type type;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cmt-show", 1) {
+        /* No options */
+    }
+
+    if (!strcmp(argv[optind], "cache-occupancy"))
+        type = LIBXL_PSR_CMT_TYPE_CACHE_OCCUPANCY;
+    else if (!strcmp(argv[optind], "total-mem-bandwidth"))
+        type = LIBXL_PSR_CMT_TYPE_TOTAL_MEM_COUNT;
+    else if (!strcmp(argv[optind], "local-mem-bandwidth"))
+        type = LIBXL_PSR_CMT_TYPE_LOCAL_MEM_COUNT;
+    else {
+        help("psr-cmt-show");
+        return 2;
+    }
+
+    if (optind + 1 >= argc)
+        domid = INVALID_DOMID;
+    else if (optind + 1 == argc - 1)
+        domid = xfind_domain(argv[optind + 1]);
+    else {
+        help("psr-cmt-show");
+        return 2;
+    }
+
+    ret = psr_cmt_show(type, domid);
+
+    return ret;
+}
+#endif
+
+#ifdef LIBXL_HAVE_PSR_CAT
+static int psr_cat_hwinfo(void)
+{
+    int rc;
+    int i, nr;
+    uint32_t l3_cache_size;
+    libxl_psr_cat_info *info;
+
+    printf("Cache Allocation Technology (CAT):\n");
+
+    rc = libxl_psr_cat_get_l3_info(ctx, &info, &nr);
+    if (rc) {
+        fprintf(stderr, "Failed to get cat info\n");
+        return rc;
+    }
+
+    for (i = 0; i < nr; i++) {
+        rc = libxl_psr_cmt_get_l3_cache_size(ctx, info[i].id, &l3_cache_size);
+        if (rc) {
+            fprintf(stderr, "Failed to get l3 cache size for socket:%d\n",
+                    info[i].id);
+            goto out;
+        }
+        printf("%-16s: %u\n", "Socket ID", info[i].id);
+        printf("%-16s: %uKB\n", "L3 Cache", l3_cache_size);
+        printf("%-16s: %s\n", "CDP Status",
+               info[i].cdp_enabled ? "Enabled" : "Disabled");
+        printf("%-16s: %u\n", "Maximum COS", info[i].cos_max);
+        printf("%-16s: %u\n", "CBM length", info[i].cbm_len);
+        printf("%-16s: %#llx\n", "Default CBM",
+               (1ull << info[i].cbm_len) - 1);
+    }
+
+out:
+    libxl_psr_cat_info_list_free(info, nr);
+    return rc;
+}
+
+static void psr_cat_print_one_domain_cbm_type(uint32_t domid, uint32_t socketid,
+                                              libxl_psr_cbm_type type)
+{
+    uint64_t cbm;
+
+    if (!libxl_psr_cat_get_cbm(ctx, domid, type, socketid, &cbm))
+        printf("%#16"PRIx64, cbm);
+    else
+        printf("%16s", "error");
+}
+
+static void psr_cat_print_one_domain_cbm(uint32_t domid, uint32_t socketid,
+                                         bool cdp_enabled)
+{
+    char *domain_name;
+
+    domain_name = libxl_domid_to_name(ctx, domid);
+    printf("%5d%25s", domid, domain_name);
+    free(domain_name);
+
+    if (!cdp_enabled) {
+        psr_cat_print_one_domain_cbm_type(domid, socketid,
+                                          LIBXL_PSR_CBM_TYPE_L3_CBM);
+    } else {
+        psr_cat_print_one_domain_cbm_type(domid, socketid,
+                                          LIBXL_PSR_CBM_TYPE_L3_CBM_CODE);
+        psr_cat_print_one_domain_cbm_type(domid, socketid,
+                                          LIBXL_PSR_CBM_TYPE_L3_CBM_DATA);
+    }
+
+    printf("\n");
+}
+
+static int psr_cat_print_domain_cbm(uint32_t domid, uint32_t socketid,
+                                    bool cdp_enabled)
+{
+    int i, nr_domains;
+    libxl_dominfo *list;
+
+    if (domid != INVALID_DOMID) {
+        psr_cat_print_one_domain_cbm(domid, socketid, cdp_enabled);
+        return 0;
+    }
+
+    if (!(list = libxl_list_domain(ctx, &nr_domains))) {
+        fprintf(stderr, "Failed to get domain list for cbm display\n");
+        return -1;
+    }
+
+    for (i = 0; i < nr_domains; i++)
+        psr_cat_print_one_domain_cbm(list[i].domid, socketid, cdp_enabled);
+    libxl_dominfo_list_free(list, nr_domains);
+
+    return 0;
+}
+
+static int psr_cat_print_socket(uint32_t domid, libxl_psr_cat_info *info)
+{
+    int rc;
+    uint32_t l3_cache_size;
+
+    rc = libxl_psr_cmt_get_l3_cache_size(ctx, info->id, &l3_cache_size);
+    if (rc) {
+        fprintf(stderr, "Failed to get l3 cache size for socket:%d\n",
+                info->id);
+        return -1;
+    }
+
+    printf("%-16s: %u\n", "Socket ID", info->id);
+    printf("%-16s: %uKB\n", "L3 Cache", l3_cache_size);
+    printf("%-16s: %#llx\n", "Default CBM", (1ull << info->cbm_len) - 1);
+    if (info->cdp_enabled)
+        printf("%5s%25s%16s%16s\n", "ID", "NAME", "CBM (code)", "CBM (data)");
+    else
+        printf("%5s%25s%16s\n", "ID", "NAME", "CBM");
+
+    return psr_cat_print_domain_cbm(domid, info->id, info->cdp_enabled);
+}
+
+static int psr_cat_show(uint32_t domid)
+{
+    int i, nr;
+    int rc;
+    libxl_psr_cat_info *info;
+
+    rc = libxl_psr_cat_get_l3_info(ctx, &info, &nr);
+    if (rc) {
+        fprintf(stderr, "Failed to get cat info\n");
+        return rc;
+    }
+
+    for (i = 0; i < nr; i++) {
+        rc = psr_cat_print_socket(domid, info + i);
+        if (rc)
+            goto out;
+    }
+
+out:
+    libxl_psr_cat_info_list_free(info, nr);
+    return rc;
+}
+
+int main_psr_cat_cbm_set(int argc, char **argv)
+{
+    uint32_t domid;
+    libxl_psr_cbm_type type;
+    uint64_t cbm;
+    int ret, opt = 0;
+    int opt_data = 0, opt_code = 0;
+    libxl_bitmap target_map;
+    char *value;
+    libxl_string_list socket_list;
+    unsigned long start, end;
+    int i, j, len;
+
+    static struct option opts[] = {
+        {"socket", 1, 0, 's'},
+        {"data", 0, 0, 'd'},
+        {"code", 0, 0, 'c'},
+        COMMON_LONG_OPTS
+    };
+
+    libxl_socket_bitmap_alloc(ctx, &target_map, 0);
+    libxl_bitmap_set_none(&target_map);
+
+    SWITCH_FOREACH_OPT(opt, "s:cd", opts, "psr-cat-cbm-set", 2) {
+    case 's':
+        trim(isspace, optarg, &value);
+        split_string_into_string_list(value, ",", &socket_list);
+        len = libxl_string_list_length(&socket_list);
+        for (i = 0; i < len; i++) {
+            parse_range(socket_list[i], &start, &end);
+            for (j = start; j <= end; j++)
+                libxl_bitmap_set(&target_map, j);
+        }
+
+        libxl_string_list_dispose(&socket_list);
+        free(value);
+        break;
+    case 'd':
+        opt_data = 1;
+        break;
+    case 'c':
+        opt_code = 1;
+        break;
+    }
+
+    if (opt_data && opt_code) {
+        fprintf(stderr, "Cannot handle -c and -d at the same time\n");
+        return -1;
+    } else if (opt_data) {
+        type = LIBXL_PSR_CBM_TYPE_L3_CBM_DATA;
+    } else if (opt_code) {
+        type = LIBXL_PSR_CBM_TYPE_L3_CBM_CODE;
+    } else {
+        type = LIBXL_PSR_CBM_TYPE_L3_CBM;
+    }
+
+    if (libxl_bitmap_is_empty(&target_map))
+        libxl_bitmap_set_any(&target_map);
+
+    if (argc != optind + 2) {
+        help("psr-cat-cbm-set");
+        return 2;
+    }
+
+    domid = xfind_domain(argv[optind]);
+    cbm = strtoll(argv[optind + 1], NULL , 0);
+
+    ret = libxl_psr_cat_set_cbm(ctx, domid, type, &target_map, cbm);
+
+    libxl_bitmap_dispose(&target_map);
+    return ret;
+}
+
+int main_psr_cat_show(int argc, char **argv)
+{
+    int opt;
+    uint32_t domid;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "psr-cat-show", 0) {
+        /* No options */
+    }
+
+    if (optind >= argc)
+        domid = INVALID_DOMID;
+    else if (optind == argc - 1)
+        domid = xfind_domain(argv[optind]);
+    else {
+        help("psr-cat-show");
+        return 2;
+    }
+
+    return psr_cat_show(domid);
+}
+
+int main_psr_hwinfo(int argc, char **argv)
+{
+    int opt, ret = 0;
+    bool all = true, cmt = false, cat = false;
+    static struct option opts[] = {
+        {"cmt", 0, 0, 'm'},
+        {"cat", 0, 0, 'a'},
+        COMMON_LONG_OPTS
+    };
+
+    SWITCH_FOREACH_OPT(opt, "ma", opts, "psr-hwinfo", 0) {
+    case 'm':
+        all = false; cmt = true;
+        break;
+    case 'a':
+        all = false; cat = true;
+        break;
+    }
+
+    if (!ret && (all || cmt))
+        ret = psr_cmt_hwinfo();
+
+    if (!ret && (all || cat))
+        ret = psr_cat_hwinfo();
+
+    return ret;
+}
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 23/29] xl: split out functions to print out information
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (21 preceding siblings ...)
  2017-02-24 16:13 ` [PATCH 22/29] xl: split out psr " Wei Liu
@ 2017-02-24 16:13 ` Wei Liu
  2017-02-27 16:00   ` Ian Jackson
  2017-02-24 16:13 ` [PATCH 24/29] xl: split out vnc and console related code Wei Liu
                   ` (5 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:13 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   2 +-
 tools/xl/xl_cmdimpl.c | 883 +----------------------------------------------
 tools/xl/xl_info.c    | 925 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 929 insertions(+), 881 deletions(-)
 create mode 100644 tools/xl/xl_info.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index fdb64fed1d..c51106e49e 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -19,7 +19,7 @@ XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
 XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
 XL_OBJS += xl_vtpm.o xl_block.o xl_nic.o xl_usb.o
 XL_OBJS += xl_sched.o xl_pci.o xl_vcpu.o xl_cd.o xl_mem.o
-XL_OBJS += xl_psr.o
+XL_OBJS += xl_psr.o xl_info.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index f6942ffbe8..1de5445e7f 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -222,80 +222,6 @@ release_lock:
     return rc;
 }
 
-static yajl_gen_status printf_info_one_json(yajl_gen hand, int domid,
-                                            libxl_domain_config *d_config)
-{
-    yajl_gen_status s;
-
-    s = yajl_gen_map_open(hand);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_string(hand, (const unsigned char *)"domid",
-                        sizeof("domid")-1);
-    if (s != yajl_gen_status_ok)
-        goto out;
-    if (domid != -1)
-        s = yajl_gen_integer(hand, domid);
-    else
-        s = yajl_gen_null(hand);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_string(hand, (const unsigned char *)"config",
-                        sizeof("config")-1);
-    if (s != yajl_gen_status_ok)
-        goto out;
-    s = libxl_domain_config_gen_json(hand, d_config);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_map_close(hand);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-out:
-    return s;
-}
-
-static void printf_info(enum output_format output_format,
-                        int domid,
-                        libxl_domain_config *d_config, FILE *fh)
-{
-    if (output_format == OUTPUT_FORMAT_SXP)
-        return printf_info_sexp(domid, d_config, fh);
-
-    const char *buf;
-    libxl_yajl_length len = 0;
-    yajl_gen_status s;
-    yajl_gen hand;
-
-    hand = libxl_yajl_gen_alloc(NULL);
-    if (!hand) {
-        fprintf(stderr, "unable to allocate JSON generator\n");
-        return;
-    }
-
-    s = printf_info_one_json(hand, domid, d_config);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_get_buf(hand, (const unsigned char **)&buf, &len);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    fputs(buf, fh);
-
-out:
-    yajl_gen_free(hand);
-
-    if (s != yajl_gen_status_ok)
-        fprintf(stderr,
-                "unable to format domain config as JSON (YAJL:%d)\n", s);
-
-    xflush_stream(fh);
-}
-
 static int do_daemonize(char *name, const char *pidfile)
 {
     char *fullname;
@@ -1320,165 +1246,6 @@ static void reboot_domain(uint32_t domid, libxl_evgen_domain_death **deathw,
     }
 }
 
-static void list_domains_details(const libxl_dominfo *info, int nb_domain)
-{
-    libxl_domain_config d_config;
-
-    int i, rc;
-
-    yajl_gen hand = NULL;
-    yajl_gen_status s;
-    const char *buf;
-    libxl_yajl_length yajl_len = 0;
-
-    if (default_output_format == OUTPUT_FORMAT_JSON) {
-        hand = libxl_yajl_gen_alloc(NULL);
-        if (!hand) {
-            fprintf(stderr, "unable to allocate JSON generator\n");
-            return;
-        }
-
-        s = yajl_gen_array_open(hand);
-        if (s != yajl_gen_status_ok)
-            goto out;
-    } else
-        s = yajl_gen_status_ok;
-
-    for (i = 0; i < nb_domain; i++) {
-        libxl_domain_config_init(&d_config);
-        rc = libxl_retrieve_domain_configuration(ctx, info[i].domid, &d_config);
-        if (rc)
-            continue;
-        if (default_output_format == OUTPUT_FORMAT_JSON)
-            s = printf_info_one_json(hand, info[i].domid, &d_config);
-        else
-            printf_info_sexp(info[i].domid, &d_config, stdout);
-        libxl_domain_config_dispose(&d_config);
-        if (s != yajl_gen_status_ok)
-            goto out;
-    }
-
-    if (default_output_format == OUTPUT_FORMAT_JSON) {
-        s = yajl_gen_array_close(hand);
-        if (s != yajl_gen_status_ok)
-            goto out;
-
-        s = yajl_gen_get_buf(hand, (const unsigned char **)&buf, &yajl_len);
-        if (s != yajl_gen_status_ok)
-            goto out;
-
-        puts(buf);
-    }
-
-out:
-    if (default_output_format == OUTPUT_FORMAT_JSON) {
-        yajl_gen_free(hand);
-        if (s != yajl_gen_status_ok)
-            fprintf(stderr,
-                    "unable to format domain config as JSON (YAJL:%d)\n", s);
-    }
-}
-
-static void list_domains(bool verbose, bool context, bool claim, bool numa,
-                         bool cpupool, const libxl_dominfo *info, int nb_domain)
-{
-    int i;
-    static const char shutdown_reason_letters[]= "-rscwS";
-    libxl_bitmap nodemap;
-    libxl_physinfo physinfo;
-
-    libxl_bitmap_init(&nodemap);
-    libxl_physinfo_init(&physinfo);
-
-    printf("Name                                        ID   Mem VCPUs\tState\tTime(s)");
-    if (verbose) printf("   UUID                            Reason-Code\tSecurity Label");
-    if (context && !verbose) printf("   Security Label");
-    if (claim) printf("  Claimed");
-    if (cpupool) printf("         Cpupool");
-    if (numa) {
-        if (libxl_node_bitmap_alloc(ctx, &nodemap, 0)) {
-            fprintf(stderr, "libxl_node_bitmap_alloc_failed.\n");
-            exit(EXIT_FAILURE);
-        }
-        if (libxl_get_physinfo(ctx, &physinfo) != 0) {
-            fprintf(stderr, "libxl_physinfo failed.\n");
-            libxl_bitmap_dispose(&nodemap);
-            exit(EXIT_FAILURE);
-        }
-
-        printf(" NODE Affinity");
-    }
-    printf("\n");
-    for (i = 0; i < nb_domain; i++) {
-        char *domname;
-        libxl_shutdown_reason shutdown_reason;
-        domname = libxl_domid_to_name(ctx, info[i].domid);
-        shutdown_reason = info[i].shutdown ? info[i].shutdown_reason : 0;
-        printf("%-40s %5d %5lu %5d     %c%c%c%c%c%c  %8.1f",
-                domname,
-                info[i].domid,
-                (unsigned long) ((info[i].current_memkb +
-                    info[i].outstanding_memkb)/ 1024),
-                info[i].vcpu_online,
-                info[i].running ? 'r' : '-',
-                info[i].blocked ? 'b' : '-',
-                info[i].paused ? 'p' : '-',
-                info[i].shutdown ? 's' : '-',
-                (shutdown_reason >= 0 &&
-                 shutdown_reason < sizeof(shutdown_reason_letters)-1
-                 ? shutdown_reason_letters[shutdown_reason] : '?'),
-                info[i].dying ? 'd' : '-',
-                ((float)info[i].cpu_time / 1e9));
-        free(domname);
-        if (verbose) {
-            printf(" " LIBXL_UUID_FMT, LIBXL_UUID_BYTES(info[i].uuid));
-            if (info[i].shutdown) printf(" %8x", shutdown_reason);
-            else printf(" %8s", "-");
-        }
-        if (claim)
-            printf(" %5lu", (unsigned long)info[i].outstanding_memkb / 1024);
-        if (verbose || context)
-            printf(" %16s", info[i].ssid_label ? : "-");
-        if (cpupool) {
-            char *poolname = libxl_cpupoolid_to_name(ctx, info[i].cpupool);
-            printf("%16s", poolname);
-            free(poolname);
-        }
-        if (numa) {
-            libxl_domain_get_nodeaffinity(ctx, info[i].domid, &nodemap);
-
-            putchar(' ');
-            print_bitmap(nodemap.map, physinfo.nr_nodes, stdout);
-        }
-        putchar('\n');
-    }
-
-    libxl_bitmap_dispose(&nodemap);
-    libxl_physinfo_dispose(&physinfo);
-}
-
-static void list_vm(void)
-{
-    libxl_vminfo *info;
-    char *domname;
-    int nb_vm, i;
-
-    info = libxl_list_vm(ctx, &nb_vm);
-
-    if (!info) {
-        fprintf(stderr, "libxl_list_vm failed.\n");
-        exit(EXIT_FAILURE);
-    }
-    printf("UUID                                  ID    name\n");
-    for (i = 0; i < nb_vm; i++) {
-        domname = libxl_domid_to_name(ctx, info[i].domid);
-        printf(LIBXL_UUID_FMT "  %d    %-30s\n", LIBXL_UUID_BYTES(info[i].uuid),
-            info[i].domid, domname);
-        free(domname);
-    }
-    libxl_vminfo_list_free(info, nb_vm);
-}
-
 static void core_dump_domain(uint32_t domid, const char *filename)
 {
     int rc;
@@ -2412,99 +2179,6 @@ int main_reboot(int argc, char **argv)
     return main_shutdown_or_reboot(1, argc, argv);
 }
 
-int main_list(int argc, char **argv)
-{
-    int opt;
-    bool verbose = false;
-    bool context = false;
-    bool details = false;
-    bool cpupool = false;
-    bool numa = false;
-    static struct option opts[] = {
-        {"long", 0, 0, 'l'},
-        {"verbose", 0, 0, 'v'},
-        {"context", 0, 0, 'Z'},
-        {"cpupool", 0, 0, 'c'},
-        {"numa", 0, 0, 'n'},
-        COMMON_LONG_OPTS
-    };
-
-    libxl_dominfo info_buf;
-    libxl_dominfo *info, *info_free=0;
-    int nb_domain, rc;
-
-    SWITCH_FOREACH_OPT(opt, "lvhZcn", opts, "list", 0) {
-    case 'l':
-        details = true;
-        break;
-    case 'v':
-        verbose = true;
-        break;
-    case 'Z':
-        context = true;
-        break;
-    case 'c':
-        cpupool = true;
-        break;
-    case 'n':
-        numa = true;
-        break;
-    }
-
-    libxl_dominfo_init(&info_buf);
-
-    if (optind >= argc) {
-        info = libxl_list_domain(ctx, &nb_domain);
-        if (!info) {
-            fprintf(stderr, "libxl_list_domain failed.\n");
-            return EXIT_FAILURE;
-        }
-        info_free = info;
-    } else if (optind == argc-1) {
-        uint32_t domid = xfind_domain(argv[optind]);
-        rc = libxl_domain_info(ctx, &info_buf, domid);
-        if (rc == ERROR_DOMAIN_NOTFOUND) {
-            fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
-                argv[optind]);
-            return EXIT_FAILURE;
-        }
-        if (rc) {
-            fprintf(stderr, "libxl_domain_info failed (code %d).\n", rc);
-            return EXIT_FAILURE;
-        }
-        info = &info_buf;
-        nb_domain = 1;
-    } else {
-        help("list");
-        return EXIT_FAILURE;
-    }
-
-    if (details)
-        list_domains_details(info, nb_domain);
-    else
-        list_domains(verbose, context, false /* claim */, numa, cpupool,
-                     info, nb_domain);
-
-    if (info_free)
-        libxl_dominfo_list_free(info, nb_domain);
-
-    libxl_dominfo_dispose(&info_buf);
-
-    return EXIT_SUCCESS;
-}
-
-int main_vm_list(int argc, char **argv)
-{
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "vm-list", 0) {
-        /* No options */
-    }
-
-    list_vm();
-    return EXIT_SUCCESS;
-}
-
 int main_create(int argc, char **argv)
 {
     const char *filename = NULL;
@@ -2600,6 +2274,9 @@ int main_create(int argc, char **argv)
     return 0;
 }
 
+extern void printf_info(enum output_format output_format,
+                        int domid,
+                        libxl_domain_config *d_config, FILE *fh);
 int main_config_update(int argc, char **argv)
 {
     uint32_t domid;
@@ -2737,309 +2414,6 @@ int main_button_press(int argc, char **argv)
     return 0;
 }
 
-/* Possibly select a specific piece of `xl info` to print. */
-static const char *info_name;
-static int maybe_printf(const char *fmt, ...) __attribute__((format(printf,1,2)));
-static int maybe_printf(const char *fmt, ...)
-{
-    va_list ap;
-    char *str;
-    int count = 0;
-
-    va_start(ap, fmt);
-    if (vasprintf(&str, fmt, ap) != -1) {
-        if (info_name) {
-            char *s;
-
-            if (!strncmp(str, info_name, strlen(info_name)) &&
-                (s = strchr(str, ':')) && s[1] == ' ')
-                count = fputs(&s[2], stdout);
-        } else
-            count = fputs(str, stdout);
-
-        free(str);
-    }
-    va_end(ap);
-
-    return count;
-}
-
-static void output_xeninfo(void)
-{
-    const libxl_version_info *info;
-    libxl_scheduler sched;
-    int rc;
-
-    if (!(info = libxl_get_version_info(ctx))) {
-        fprintf(stderr, "libxl_get_version_info failed.\n");
-        return;
-    }
-
-    rc = libxl_get_scheduler(ctx);
-    if (rc < 0) {
-        fprintf(stderr, "get_scheduler sysctl failed.\n");
-        return;
-    }
-    sched = rc;
-
-    maybe_printf("xen_major              : %d\n", info->xen_version_major);
-    maybe_printf("xen_minor              : %d\n", info->xen_version_minor);
-    maybe_printf("xen_extra              : %s\n", info->xen_version_extra);
-    maybe_printf("xen_version            : %d.%d%s\n", info->xen_version_major,
-           info->xen_version_minor, info->xen_version_extra);
-    maybe_printf("xen_caps               : %s\n", info->capabilities);
-    maybe_printf("xen_scheduler          : %s\n", libxl_scheduler_to_string(sched));
-    maybe_printf("xen_pagesize           : %u\n", info->pagesize);
-    maybe_printf("platform_params        : virt_start=0x%"PRIx64"\n", info->virt_start);
-    maybe_printf("xen_changeset          : %s\n", info->changeset);
-    maybe_printf("xen_commandline        : %s\n", info->commandline);
-    maybe_printf("cc_compiler            : %s\n", info->compiler);
-    maybe_printf("cc_compile_by          : %s\n", info->compile_by);
-    maybe_printf("cc_compile_domain      : %s\n", info->compile_domain);
-    maybe_printf("cc_compile_date        : %s\n", info->compile_date);
-    maybe_printf("build_id               : %s\n", info->build_id);
-
-    return;
-}
-
-static void output_nodeinfo(void)
-{
-    struct utsname utsbuf;
-
-    if (uname(&utsbuf) < 0)
-        return;
-
-    maybe_printf("host                   : %s\n", utsbuf.nodename);
-    maybe_printf("release                : %s\n", utsbuf.release);
-    maybe_printf("version                : %s\n", utsbuf.version);
-    maybe_printf("machine                : %s\n", utsbuf.machine);
-}
-
-static void output_physinfo(void)
-{
-    libxl_physinfo info;
-    const libxl_version_info *vinfo;
-    unsigned int i;
-    libxl_bitmap cpumap;
-    int n = 0;
-
-    if (libxl_get_physinfo(ctx, &info) != 0) {
-        fprintf(stderr, "libxl_physinfo failed.\n");
-        return;
-    }
-    maybe_printf("nr_cpus                : %d\n", info.nr_cpus);
-    maybe_printf("max_cpu_id             : %d\n", info.max_cpu_id);
-    maybe_printf("nr_nodes               : %d\n", info.nr_nodes);
-    maybe_printf("cores_per_socket       : %d\n", info.cores_per_socket);
-    maybe_printf("threads_per_core       : %d\n", info.threads_per_core);
-    maybe_printf("cpu_mhz                : %d\n", info.cpu_khz / 1000);
-
-    maybe_printf("hw_caps                : %08x:%08x:%08x:%08x:%08x:%08x:%08x:%08x\n",
-         info.hw_cap[0], info.hw_cap[1], info.hw_cap[2], info.hw_cap[3],
-         info.hw_cap[4], info.hw_cap[5], info.hw_cap[6], info.hw_cap[7]
-        );
-
-    maybe_printf("virt_caps              :%s%s\n",
-         info.cap_hvm ? " hvm" : "",
-         info.cap_hvm_directio ? " hvm_directio" : ""
-        );
-
-    vinfo = libxl_get_version_info(ctx);
-    if (vinfo) {
-        i = (1 << 20) / vinfo->pagesize;
-        maybe_printf("total_memory           : %"PRIu64"\n", info.total_pages / i);
-        maybe_printf("free_memory            : %"PRIu64"\n", (info.free_pages - info.outstanding_pages) / i);
-        maybe_printf("sharing_freed_memory   : %"PRIu64"\n", info.sharing_freed_pages / i);
-        maybe_printf("sharing_used_memory    : %"PRIu64"\n", info.sharing_used_frames / i);
-        maybe_printf("outstanding_claims     : %"PRIu64"\n", info.outstanding_pages / i);
-    }
-    if (!libxl_get_freecpus(ctx, &cpumap)) {
-        libxl_for_each_bit(i, cpumap)
-            if (libxl_bitmap_test(&cpumap, i))
-                n++;
-        maybe_printf("free_cpus              : %d\n", n);
-        free(cpumap.map);
-    }
-    libxl_physinfo_dispose(&info);
-    return;
-}
-
-static void output_numainfo(void)
-{
-    libxl_numainfo *info;
-    int i, j, nr;
-
-    info = libxl_get_numainfo(ctx, &nr);
-    if (info == NULL) {
-        fprintf(stderr, "libxl_get_numainfo failed.\n");
-        return;
-    }
-
-    printf("numa_info              :\n");
-    printf("node:    memsize    memfree    distances\n");
-
-    for (i = 0; i < nr; i++) {
-        if (info[i].size != LIBXL_NUMAINFO_INVALID_ENTRY) {
-            printf("%4d:    %6"PRIu64"     %6"PRIu64"      %d", i,
-                   info[i].size >> 20, info[i].free >> 20,
-                   info[i].dists[0]);
-            for (j = 1; j < info[i].num_dists; j++)
-                printf(",%d", info[i].dists[j]);
-            printf("\n");
-        }
-    }
-
-    libxl_numainfo_list_free(info, nr);
-
-    return;
-}
-
-static void output_topologyinfo(void)
-{
-    libxl_cputopology *cpuinfo;
-    int i, nr;
-    libxl_pcitopology *pciinfo;
-    int valid_devs = 0;
-
-
-    cpuinfo = libxl_get_cpu_topology(ctx, &nr);
-    if (cpuinfo == NULL) {
-        fprintf(stderr, "libxl_get_cpu_topology failed.\n");
-        return;
-    }
-
-    printf("cpu_topology           :\n");
-    printf("cpu:    core    socket     node\n");
-
-    for (i = 0; i < nr; i++) {
-        if (cpuinfo[i].core != LIBXL_CPUTOPOLOGY_INVALID_ENTRY)
-            printf("%3d:    %4d     %4d     %4d\n", i,
-                   cpuinfo[i].core, cpuinfo[i].socket, cpuinfo[i].node);
-    }
-
-    libxl_cputopology_list_free(cpuinfo, nr);
-
-    pciinfo = libxl_get_pci_topology(ctx, &nr);
-    if (pciinfo == NULL) {
-        fprintf(stderr, "libxl_get_pci_topology failed.\n");
-        return;
-    }
-
-    printf("device topology        :\n");
-    printf("device           node\n");
-    for (i = 0; i < nr; i++) {
-        if (pciinfo[i].node != LIBXL_PCITOPOLOGY_INVALID_ENTRY) {
-            printf("%04x:%02x:%02x.%01x      %d\n", pciinfo[i].seg,
-                   pciinfo[i].bus,
-                   ((pciinfo[i].devfn >> 3) & 0x1f), (pciinfo[i].devfn & 7),
-                   pciinfo[i].node);
-            valid_devs++;
-        }
-    }
-
-    if (valid_devs == 0)
-        printf("No device topology data available\n");
-
-    libxl_pcitopology_list_free(pciinfo, nr);
-
-    return;
-}
-
-static void print_info(int numa)
-{
-    output_nodeinfo();
-
-    output_physinfo();
-
-    if (numa) {
-        output_topologyinfo();
-        output_numainfo();
-    }
-    output_xeninfo();
-
-    maybe_printf("xend_config_format     : 4\n");
-
-    return;
-}
-
-int main_info(int argc, char **argv)
-{
-    int opt;
-    static struct option opts[] = {
-        {"numa", 0, 0, 'n'},
-        COMMON_LONG_OPTS
-    };
-    int numa = 0;
-
-    SWITCH_FOREACH_OPT(opt, "n", opts, "info", 0) {
-    case 'n':
-        numa = 1;
-        break;
-    }
-
-    /*
-     * If an extra argument is provided, filter out a specific piece of
-     * information.
-     */
-    if (numa == 0 && argc > optind)
-        info_name = argv[optind];
-
-    print_info(numa);
-    return 0;
-}
-
-int main_domid(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    const char *domname = NULL;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "domid", 1) {
-        /* No options */
-    }
-
-    domname = argv[optind];
-
-    if (libxl_name_to_domid(ctx, domname, &domid)) {
-        fprintf(stderr, "Can't get domid of domain name '%s', maybe this domain does not exist.\n", domname);
-        return EXIT_FAILURE;
-    }
-
-    printf("%u\n", domid);
-
-    return EXIT_SUCCESS;
-}
-
-int main_domname(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    char *domname = NULL;
-    char *endptr = NULL;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "domname", 1) {
-        /* No options */
-    }
-
-    domid = strtol(argv[optind], &endptr, 10);
-    if (domid == 0 && !strcmp(endptr, argv[optind])) {
-        /*no digits at all*/
-        fprintf(stderr, "Invalid domain id.\n\n");
-        return EXIT_FAILURE;
-    }
-
-    domname = libxl_domid_to_name(ctx, domid);
-    if (!domname) {
-        fprintf(stderr, "Can't get domain name of domain id '%u', maybe this domain does not exist.\n", domid);
-        return EXIT_FAILURE;
-    }
-
-    printf("%s\n", domname);
-    free(domname);
-
-    return EXIT_SUCCESS;
-}
-
 int main_rename(int argc, char **argv)
 {
     uint32_t domid;
@@ -3140,43 +2514,6 @@ int main_debug_keys(int argc, char **argv)
     return EXIT_SUCCESS;
 }
 
-int main_dmesg(int argc, char **argv)
-{
-    unsigned int clear = 0;
-    libxl_xen_console_reader *cr;
-    char *line;
-    int opt, ret = 1;
-
-    SWITCH_FOREACH_OPT(opt, "c", NULL, "dmesg", 0) {
-    case 'c':
-        clear = 1;
-        break;
-    }
-
-    cr = libxl_xen_console_read_start(ctx, clear);
-    if (!cr)
-        goto finish;
-
-    while ((ret = libxl_xen_console_read_line(ctx, cr, &line)) > 0)
-        printf("%s", line);
-
-finish:
-    if (cr)
-        libxl_xen_console_read_finish(ctx, cr);
-    return ret ? EXIT_FAILURE : EXIT_SUCCESS;
-}
-
-int main_top(int argc, char **argv)
-{
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "top", 0) {
-        /* No options */
-    }
-
-    return system("xentop");
-}
-
 int main_channellist(int argc, char **argv)
 {
     int opt;
@@ -3221,220 +2558,6 @@ int main_channellist(int argc, char **argv)
     return 0;
 }
 
-static char *uptime_to_string(unsigned long uptime, int short_mode)
-{
-    int sec, min, hour, day;
-    char *time_string;
-
-    day = (int)(uptime / 86400);
-    uptime -= (day * 86400);
-    hour = (int)(uptime / 3600);
-    uptime -= (hour * 3600);
-    min = (int)(uptime / 60);
-    uptime -= (min * 60);
-    sec = uptime;
-
-    if (short_mode)
-        if (day > 1)
-            xasprintf(&time_string, "%d days, %2d:%02d", day, hour, min);
-        else if (day == 1)
-            xasprintf(&time_string, "%d day, %2d:%02d", day, hour, min);
-        else
-            xasprintf(&time_string, "%2d:%02d", hour, min);
-    else
-        if (day > 1)
-            xasprintf(&time_string, "%d days, %2d:%02d:%02d", day, hour, min, sec);
-        else if (day == 1)
-            xasprintf(&time_string, "%d day, %2d:%02d:%02d", day, hour, min, sec);
-        else
-            xasprintf(&time_string, "%2d:%02d:%02d", hour, min, sec);
-
-    return time_string;
-}
-
-int main_claims(int argc, char **argv)
-{
-    libxl_dominfo *info;
-    int opt;
-    int nb_domain;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "claims", 0) {
-        /* No options */
-    }
-
-    if (!claim_mode)
-        fprintf(stderr, "claim_mode not enabled (see man xl.conf).\n");
-
-    info = libxl_list_domain(ctx, &nb_domain);
-    if (!info) {
-        fprintf(stderr, "libxl_list_domain failed.\n");
-        return 1;
-    }
-
-    list_domains(false /* verbose */, false /* context */, true /* claim */,
-                 false /* numa */, false /* cpupool */, info, nb_domain);
-
-    libxl_dominfo_list_free(info, nb_domain);
-    return 0;
-}
-
-static char *current_time_to_string(time_t now)
-{
-    char now_str[100];
-    struct tm *tmp;
-
-    tmp = localtime(&now);
-    if (tmp == NULL) {
-        fprintf(stderr, "Get localtime error");
-        exit(-1);
-    }
-    if (strftime(now_str, sizeof(now_str), "%H:%M:%S", tmp) == 0) {
-        fprintf(stderr, "strftime returned 0");
-        exit(-1);
-    }
-    return strdup(now_str);
-}
-
-static void print_dom0_uptime(int short_mode, time_t now)
-{
-    int fd;
-    ssize_t nr;
-    char buf[512];
-    uint32_t uptime = 0;
-    char *uptime_str = NULL;
-    char *now_str = NULL;
-    char *domname;
-
-    fd = open("/proc/uptime", O_RDONLY);
-    if (fd == -1)
-        goto err;
-
-    nr = read(fd, buf, sizeof(buf) - 1);
-    if (nr == -1) {
-        close(fd);
-        goto err;
-    }
-    close(fd);
-
-    buf[nr] = '\0';
-
-    strtok(buf, " ");
-    uptime = strtoul(buf, NULL, 10);
-
-    domname = libxl_domid_to_name(ctx, 0);
-    if (short_mode)
-    {
-        now_str = current_time_to_string(now);
-        uptime_str = uptime_to_string(uptime, 1);
-        printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
-               domname, 0);
-    }
-    else
-    {
-        now_str = NULL;
-        uptime_str = uptime_to_string(uptime, 0);
-        printf("%-33s %4d %s\n", domname,
-               0, uptime_str);
-    }
-
-    free(now_str);
-    free(uptime_str);
-    free(domname);
-    return;
-err:
-    fprintf(stderr, "Can not get Dom0 uptime.\n");
-    exit(-1);
-}
-
-static void print_domU_uptime(uint32_t domuid, int short_mode, time_t now)
-{
-    uint32_t s_time = 0;
-    uint32_t uptime = 0;
-    char *uptime_str = NULL;
-    char *now_str = NULL;
-    char *domname;
-
-    s_time = libxl_vm_get_start_time(ctx, domuid);
-    if (s_time == -1)
-        return;
-    uptime = now - s_time;
-    domname = libxl_domid_to_name(ctx, domuid);
-    if (short_mode)
-    {
-        now_str = current_time_to_string(now);
-        uptime_str = uptime_to_string(uptime, 1);
-        printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
-               domname, domuid);
-    }
-    else
-    {
-        now_str = NULL;
-        uptime_str = uptime_to_string(uptime, 0);
-        printf("%-33s %4d %s\n", domname,
-               domuid, uptime_str);
-    }
-
-    free(domname);
-    free(now_str);
-    free(uptime_str);
-    return;
-}
-
-static void print_uptime(int short_mode, uint32_t doms[], int nb_doms)
-{
-    libxl_vminfo *info;
-    time_t now;
-    int nb_vm, i;
-
-    now = time(NULL);
-
-    if (!short_mode)
-        printf("%-33s %4s %s\n", "Name", "ID", "Uptime");
-
-    if (nb_doms == 0) {
-        print_dom0_uptime(short_mode, now);
-        info = libxl_list_vm(ctx, &nb_vm);
-        if (info == NULL) {
-            fprintf(stderr, "Could not list vms.\n");
-            return;
-        }
-        for (i = 0; i < nb_vm; i++) {
-            if (info[i].domid == 0) continue;
-            print_domU_uptime(info[i].domid, short_mode, now);
-        }
-        libxl_vminfo_list_free(info, nb_vm);
-    } else {
-        for (i = 0; i < nb_doms; i++) {
-            if (doms[i] == 0)
-                print_dom0_uptime(short_mode, now);
-            else
-                print_domU_uptime(doms[i], short_mode, now);
-        }
-    }
-}
-
-int main_uptime(int argc, char **argv)
-{
-    const char *dom;
-    int short_mode = 0;
-    uint32_t domains[100];
-    int nb_doms = 0;
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "s", NULL, "uptime", 0) {
-    case 's':
-        short_mode = 1;
-        break;
-    }
-
-    for (;(dom = argv[optind]) != NULL; nb_doms++,optind++)
-        domains[nb_doms] = xfind_domain(dom);
-
-    print_uptime(short_mode, domains, nb_doms);
-
-    return 0;
-}
-
 #ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
 int main_remus(int argc, char **argv)
 {
diff --git a/tools/xl/xl_info.c b/tools/xl/xl_info.c
new file mode 100644
index 0000000000..e5d5a41e49
--- /dev/null
+++ b/tools/xl/xl_info.c
@@ -0,0 +1,925 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#define _GNU_SOURCE
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <libxl.h>
+#include <libxl_json.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+
+/* Possibly select a specific piece of `xl info` to print. */
+static const char *info_name;
+static int maybe_printf(const char *fmt, ...) __attribute__((format(printf,1,2)));
+static int maybe_printf(const char *fmt, ...)
+{
+    va_list ap;
+    char *str;
+    int count = 0;
+
+    va_start(ap, fmt);
+    if (vasprintf(&str, fmt, ap) != -1) {
+        if (info_name) {
+            char *s;
+
+            if (!strncmp(str, info_name, strlen(info_name)) &&
+                (s = strchr(str, ':')) && s[1] == ' ')
+                count = fputs(&s[2], stdout);
+        } else
+            count = fputs(str, stdout);
+
+        free(str);
+    }
+    va_end(ap);
+
+    return count;
+}
+
+static yajl_gen_status printf_info_one_json(yajl_gen hand, int domid,
+                                            libxl_domain_config *d_config)
+{
+    yajl_gen_status s;
+
+    s = yajl_gen_map_open(hand);
+    if (s != yajl_gen_status_ok)
+        goto out;
+
+    s = yajl_gen_string(hand, (const unsigned char *)"domid",
+                        sizeof("domid")-1);
+    if (s != yajl_gen_status_ok)
+        goto out;
+    if (domid != -1)
+        s = yajl_gen_integer(hand, domid);
+    else
+        s = yajl_gen_null(hand);
+    if (s != yajl_gen_status_ok)
+        goto out;
+
+    s = yajl_gen_string(hand, (const unsigned char *)"config",
+                        sizeof("config")-1);
+    if (s != yajl_gen_status_ok)
+        goto out;
+    s = libxl_domain_config_gen_json(hand, d_config);
+    if (s != yajl_gen_status_ok)
+        goto out;
+
+    s = yajl_gen_map_close(hand);
+    if (s != yajl_gen_status_ok)
+        goto out;
+
+out:
+    return s;
+}
+
+void printf_info(enum output_format output_format,
+                 int domid,
+                 libxl_domain_config *d_config, FILE *fh);
+void printf_info(enum output_format output_format,
+                 int domid,
+                 libxl_domain_config *d_config, FILE *fh)
+{
+    if (output_format == OUTPUT_FORMAT_SXP)
+        return printf_info_sexp(domid, d_config, fh);
+
+    const char *buf;
+    libxl_yajl_length len = 0;
+    yajl_gen_status s;
+    yajl_gen hand;
+
+    hand = libxl_yajl_gen_alloc(NULL);
+    if (!hand) {
+        fprintf(stderr, "unable to allocate JSON generator\n");
+        return;
+    }
+
+    s = printf_info_one_json(hand, domid, d_config);
+    if (s != yajl_gen_status_ok)
+        goto out;
+
+    s = yajl_gen_get_buf(hand, (const unsigned char **)&buf, &len);
+    if (s != yajl_gen_status_ok)
+        goto out;
+
+    fputs(buf, fh);
+
+out:
+    yajl_gen_free(hand);
+
+    if (s != yajl_gen_status_ok)
+        fprintf(stderr,
+                "unable to format domain config as JSON (YAJL:%d)\n", s);
+
+    xflush_stream(fh);
+}
+
+static void output_xeninfo(void)
+{
+    const libxl_version_info *info;
+    libxl_scheduler sched;
+    int rc;
+
+    if (!(info = libxl_get_version_info(ctx))) {
+        fprintf(stderr, "libxl_get_version_info failed.\n");
+        return;
+    }
+
+    rc = libxl_get_scheduler(ctx);
+    if (rc < 0) {
+        fprintf(stderr, "get_scheduler sysctl failed.\n");
+        return;
+    }
+    sched = rc;
+
+    maybe_printf("xen_major              : %d\n", info->xen_version_major);
+    maybe_printf("xen_minor              : %d\n", info->xen_version_minor);
+    maybe_printf("xen_extra              : %s\n", info->xen_version_extra);
+    maybe_printf("xen_version            : %d.%d%s\n", info->xen_version_major,
+           info->xen_version_minor, info->xen_version_extra);
+    maybe_printf("xen_caps               : %s\n", info->capabilities);
+    maybe_printf("xen_scheduler          : %s\n", libxl_scheduler_to_string(sched));
+    maybe_printf("xen_pagesize           : %u\n", info->pagesize);
+    maybe_printf("platform_params        : virt_start=0x%"PRIx64"\n", info->virt_start);
+    maybe_printf("xen_changeset          : %s\n", info->changeset);
+    maybe_printf("xen_commandline        : %s\n", info->commandline);
+    maybe_printf("cc_compiler            : %s\n", info->compiler);
+    maybe_printf("cc_compile_by          : %s\n", info->compile_by);
+    maybe_printf("cc_compile_domain      : %s\n", info->compile_domain);
+    maybe_printf("cc_compile_date        : %s\n", info->compile_date);
+    maybe_printf("build_id               : %s\n", info->build_id);
+
+    return;
+}
+
+static void output_nodeinfo(void)
+{
+    struct utsname utsbuf;
+
+    if (uname(&utsbuf) < 0)
+        return;
+
+    maybe_printf("host                   : %s\n", utsbuf.nodename);
+    maybe_printf("release                : %s\n", utsbuf.release);
+    maybe_printf("version                : %s\n", utsbuf.version);
+    maybe_printf("machine                : %s\n", utsbuf.machine);
+}
+
+static void output_physinfo(void)
+{
+    libxl_physinfo info;
+    const libxl_version_info *vinfo;
+    unsigned int i;
+    libxl_bitmap cpumap;
+    int n = 0;
+
+    if (libxl_get_physinfo(ctx, &info) != 0) {
+        fprintf(stderr, "libxl_physinfo failed.\n");
+        return;
+    }
+    maybe_printf("nr_cpus                : %d\n", info.nr_cpus);
+    maybe_printf("max_cpu_id             : %d\n", info.max_cpu_id);
+    maybe_printf("nr_nodes               : %d\n", info.nr_nodes);
+    maybe_printf("cores_per_socket       : %d\n", info.cores_per_socket);
+    maybe_printf("threads_per_core       : %d\n", info.threads_per_core);
+    maybe_printf("cpu_mhz                : %d\n", info.cpu_khz / 1000);
+
+    maybe_printf("hw_caps                : %08x:%08x:%08x:%08x:%08x:%08x:%08x:%08x\n",
+         info.hw_cap[0], info.hw_cap[1], info.hw_cap[2], info.hw_cap[3],
+         info.hw_cap[4], info.hw_cap[5], info.hw_cap[6], info.hw_cap[7]
+        );
+
+    maybe_printf("virt_caps              :%s%s\n",
+         info.cap_hvm ? " hvm" : "",
+         info.cap_hvm_directio ? " hvm_directio" : ""
+        );
+
+    vinfo = libxl_get_version_info(ctx);
+    if (vinfo) {
+        i = (1 << 20) / vinfo->pagesize;
+        maybe_printf("total_memory           : %"PRIu64"\n", info.total_pages / i);
+        maybe_printf("free_memory            : %"PRIu64"\n", (info.free_pages - info.outstanding_pages) / i);
+        maybe_printf("sharing_freed_memory   : %"PRIu64"\n", info.sharing_freed_pages / i);
+        maybe_printf("sharing_used_memory    : %"PRIu64"\n", info.sharing_used_frames / i);
+        maybe_printf("outstanding_claims     : %"PRIu64"\n", info.outstanding_pages / i);
+    }
+    if (!libxl_get_freecpus(ctx, &cpumap)) {
+        libxl_for_each_bit(i, cpumap)
+            if (libxl_bitmap_test(&cpumap, i))
+                n++;
+        maybe_printf("free_cpus              : %d\n", n);
+        free(cpumap.map);
+    }
+    libxl_physinfo_dispose(&info);
+    return;
+}
+
+static void output_numainfo(void)
+{
+    libxl_numainfo *info;
+    int i, j, nr;
+
+    info = libxl_get_numainfo(ctx, &nr);
+    if (info == NULL) {
+        fprintf(stderr, "libxl_get_numainfo failed.\n");
+        return;
+    }
+
+    printf("numa_info              :\n");
+    printf("node:    memsize    memfree    distances\n");
+
+    for (i = 0; i < nr; i++) {
+        if (info[i].size != LIBXL_NUMAINFO_INVALID_ENTRY) {
+            printf("%4d:    %6"PRIu64"     %6"PRIu64"      %d", i,
+                   info[i].size >> 20, info[i].free >> 20,
+                   info[i].dists[0]);
+            for (j = 1; j < info[i].num_dists; j++)
+                printf(",%d", info[i].dists[j]);
+            printf("\n");
+        }
+    }
+
+    libxl_numainfo_list_free(info, nr);
+
+    return;
+}
+
+static void output_topologyinfo(void)
+{
+    libxl_cputopology *cpuinfo;
+    int i, nr;
+    libxl_pcitopology *pciinfo;
+    int valid_devs = 0;
+
+
+    cpuinfo = libxl_get_cpu_topology(ctx, &nr);
+    if (cpuinfo == NULL) {
+        fprintf(stderr, "libxl_get_cpu_topology failed.\n");
+        return;
+    }
+
+    printf("cpu_topology           :\n");
+    printf("cpu:    core    socket     node\n");
+
+    for (i = 0; i < nr; i++) {
+        if (cpuinfo[i].core != LIBXL_CPUTOPOLOGY_INVALID_ENTRY)
+            printf("%3d:    %4d     %4d     %4d\n", i,
+                   cpuinfo[i].core, cpuinfo[i].socket, cpuinfo[i].node);
+    }
+
+    libxl_cputopology_list_free(cpuinfo, nr);
+
+    pciinfo = libxl_get_pci_topology(ctx, &nr);
+    if (pciinfo == NULL) {
+        fprintf(stderr, "libxl_get_pci_topology failed.\n");
+        return;
+    }
+
+    printf("device topology        :\n");
+    printf("device           node\n");
+    for (i = 0; i < nr; i++) {
+        if (pciinfo[i].node != LIBXL_PCITOPOLOGY_INVALID_ENTRY) {
+            printf("%04x:%02x:%02x.%01x      %d\n", pciinfo[i].seg,
+                   pciinfo[i].bus,
+                   ((pciinfo[i].devfn >> 3) & 0x1f), (pciinfo[i].devfn & 7),
+                   pciinfo[i].node);
+            valid_devs++;
+        }
+    }
+
+    if (valid_devs == 0)
+        printf("No device topology data available\n");
+
+    libxl_pcitopology_list_free(pciinfo, nr);
+
+    return;
+}
+
+static void print_info(int numa)
+{
+    output_nodeinfo();
+
+    output_physinfo();
+
+    if (numa) {
+        output_topologyinfo();
+        output_numainfo();
+    }
+    output_xeninfo();
+
+    maybe_printf("xend_config_format     : 4\n");
+
+    return;
+}
+
+static void list_vm(void)
+{
+    libxl_vminfo *info;
+    char *domname;
+    int nb_vm, i;
+
+    info = libxl_list_vm(ctx, &nb_vm);
+
+    if (!info) {
+        fprintf(stderr, "libxl_list_vm failed.\n");
+        exit(EXIT_FAILURE);
+    }
+    printf("UUID                                  ID    name\n");
+    for (i = 0; i < nb_vm; i++) {
+        domname = libxl_domid_to_name(ctx, info[i].domid);
+        printf(LIBXL_UUID_FMT "  %d    %-30s\n", LIBXL_UUID_BYTES(info[i].uuid),
+            info[i].domid, domname);
+        free(domname);
+    }
+    libxl_vminfo_list_free(info, nb_vm);
+}
+
+static void list_domains(bool verbose, bool context, bool claim, bool numa,
+                         bool cpupool, const libxl_dominfo *info, int nb_domain)
+{
+    int i;
+    static const char shutdown_reason_letters[]= "-rscwS";
+    libxl_bitmap nodemap;
+    libxl_physinfo physinfo;
+
+    libxl_bitmap_init(&nodemap);
+    libxl_physinfo_init(&physinfo);
+
+    printf("Name                                        ID   Mem VCPUs\tState\tTime(s)");
+    if (verbose) printf("   UUID                            Reason-Code\tSecurity Label");
+    if (context && !verbose) printf("   Security Label");
+    if (claim) printf("  Claimed");
+    if (cpupool) printf("         Cpupool");
+    if (numa) {
+        if (libxl_node_bitmap_alloc(ctx, &nodemap, 0)) {
+            fprintf(stderr, "libxl_node_bitmap_alloc_failed.\n");
+            exit(EXIT_FAILURE);
+        }
+        if (libxl_get_physinfo(ctx, &physinfo) != 0) {
+            fprintf(stderr, "libxl_physinfo failed.\n");
+            libxl_bitmap_dispose(&nodemap);
+            exit(EXIT_FAILURE);
+        }
+
+        printf(" NODE Affinity");
+    }
+    printf("\n");
+    for (i = 0; i < nb_domain; i++) {
+        char *domname;
+        libxl_shutdown_reason shutdown_reason;
+        domname = libxl_domid_to_name(ctx, info[i].domid);
+        shutdown_reason = info[i].shutdown ? info[i].shutdown_reason : 0;
+        printf("%-40s %5d %5lu %5d     %c%c%c%c%c%c  %8.1f",
+                domname,
+                info[i].domid,
+                (unsigned long) ((info[i].current_memkb +
+                    info[i].outstanding_memkb)/ 1024),
+                info[i].vcpu_online,
+                info[i].running ? 'r' : '-',
+                info[i].blocked ? 'b' : '-',
+                info[i].paused ? 'p' : '-',
+                info[i].shutdown ? 's' : '-',
+                (shutdown_reason >= 0 &&
+                 shutdown_reason < sizeof(shutdown_reason_letters)-1
+                 ? shutdown_reason_letters[shutdown_reason] : '?'),
+                info[i].dying ? 'd' : '-',
+                ((float)info[i].cpu_time / 1e9));
+        free(domname);
+        if (verbose) {
+            printf(" " LIBXL_UUID_FMT, LIBXL_UUID_BYTES(info[i].uuid));
+            if (info[i].shutdown) printf(" %8x", shutdown_reason);
+            else printf(" %8s", "-");
+        }
+        if (claim)
+            printf(" %5lu", (unsigned long)info[i].outstanding_memkb / 1024);
+        if (verbose || context)
+            printf(" %16s", info[i].ssid_label ? : "-");
+        if (cpupool) {
+            char *poolname = libxl_cpupoolid_to_name(ctx, info[i].cpupool);
+            printf("%16s", poolname);
+            free(poolname);
+        }
+        if (numa) {
+            libxl_domain_get_nodeaffinity(ctx, info[i].domid, &nodemap);
+
+            putchar(' ');
+            print_bitmap(nodemap.map, physinfo.nr_nodes, stdout);
+        }
+        putchar('\n');
+    }
+
+    libxl_bitmap_dispose(&nodemap);
+    libxl_physinfo_dispose(&physinfo);
+}
+
+static void list_domains_details(const libxl_dominfo *info, int nb_domain)
+{
+    libxl_domain_config d_config;
+
+    int i, rc;
+
+    yajl_gen hand = NULL;
+    yajl_gen_status s;
+    const char *buf;
+    libxl_yajl_length yajl_len = 0;
+
+    if (default_output_format == OUTPUT_FORMAT_JSON) {
+        hand = libxl_yajl_gen_alloc(NULL);
+        if (!hand) {
+            fprintf(stderr, "unable to allocate JSON generator\n");
+            return;
+        }
+
+        s = yajl_gen_array_open(hand);
+        if (s != yajl_gen_status_ok)
+            goto out;
+    } else
+        s = yajl_gen_status_ok;
+
+    for (i = 0; i < nb_domain; i++) {
+        libxl_domain_config_init(&d_config);
+        rc = libxl_retrieve_domain_configuration(ctx, info[i].domid, &d_config);
+        if (rc)
+            continue;
+        if (default_output_format == OUTPUT_FORMAT_JSON)
+            s = printf_info_one_json(hand, info[i].domid, &d_config);
+        else
+            printf_info_sexp(info[i].domid, &d_config, stdout);
+        libxl_domain_config_dispose(&d_config);
+        if (s != yajl_gen_status_ok)
+            goto out;
+    }
+
+    if (default_output_format == OUTPUT_FORMAT_JSON) {
+        s = yajl_gen_array_close(hand);
+        if (s != yajl_gen_status_ok)
+            goto out;
+
+        s = yajl_gen_get_buf(hand, (const unsigned char **)&buf, &yajl_len);
+        if (s != yajl_gen_status_ok)
+            goto out;
+
+        puts(buf);
+    }
+
+out:
+    if (default_output_format == OUTPUT_FORMAT_JSON) {
+        yajl_gen_free(hand);
+        if (s != yajl_gen_status_ok)
+            fprintf(stderr,
+                    "unable to format domain config as JSON (YAJL:%d)\n", s);
+    }
+}
+
+
+int main_list(int argc, char **argv)
+{
+    int opt;
+    bool verbose = false;
+    bool context = false;
+    bool details = false;
+    bool cpupool = false;
+    bool numa = false;
+    static struct option opts[] = {
+        {"long", 0, 0, 'l'},
+        {"verbose", 0, 0, 'v'},
+        {"context", 0, 0, 'Z'},
+        {"cpupool", 0, 0, 'c'},
+        {"numa", 0, 0, 'n'},
+        COMMON_LONG_OPTS
+    };
+
+    libxl_dominfo info_buf;
+    libxl_dominfo *info, *info_free=0;
+    int nb_domain, rc;
+
+    SWITCH_FOREACH_OPT(opt, "lvhZcn", opts, "list", 0) {
+    case 'l':
+        details = true;
+        break;
+    case 'v':
+        verbose = true;
+        break;
+    case 'Z':
+        context = true;
+        break;
+    case 'c':
+        cpupool = true;
+        break;
+    case 'n':
+        numa = true;
+        break;
+    }
+
+    libxl_dominfo_init(&info_buf);
+
+    if (optind >= argc) {
+        info = libxl_list_domain(ctx, &nb_domain);
+        if (!info) {
+            fprintf(stderr, "libxl_list_domain failed.\n");
+            return EXIT_FAILURE;
+        }
+        info_free = info;
+    } else if (optind == argc-1) {
+        uint32_t domid = xfind_domain(argv[optind]);
+        rc = libxl_domain_info(ctx, &info_buf, domid);
+        if (rc == ERROR_DOMAIN_NOTFOUND) {
+            fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
+                argv[optind]);
+            return EXIT_FAILURE;
+        }
+        if (rc) {
+            fprintf(stderr, "libxl_domain_info failed (code %d).\n", rc);
+            return EXIT_FAILURE;
+        }
+        info = &info_buf;
+        nb_domain = 1;
+    } else {
+        help("list");
+        return EXIT_FAILURE;
+    }
+
+    if (details)
+        list_domains_details(info, nb_domain);
+    else
+        list_domains(verbose, context, false /* claim */, numa, cpupool,
+                     info, nb_domain);
+
+    if (info_free)
+        libxl_dominfo_list_free(info, nb_domain);
+
+    libxl_dominfo_dispose(&info_buf);
+
+    return EXIT_SUCCESS;
+}
+
+int main_vm_list(int argc, char **argv)
+{
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vm-list", 0) {
+        /* No options */
+    }
+
+    list_vm();
+    return EXIT_SUCCESS;
+}
+
+int main_info(int argc, char **argv)
+{
+    int opt;
+    static struct option opts[] = {
+        {"numa", 0, 0, 'n'},
+        COMMON_LONG_OPTS
+    };
+    int numa = 0;
+
+    SWITCH_FOREACH_OPT(opt, "n", opts, "info", 0) {
+    case 'n':
+        numa = 1;
+        break;
+    }
+
+    /*
+     * If an extra argument is provided, filter out a specific piece of
+     * information.
+     */
+    if (numa == 0 && argc > optind)
+        info_name = argv[optind];
+
+    print_info(numa);
+    return 0;
+}
+
+int main_domid(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    const char *domname = NULL;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "domid", 1) {
+        /* No options */
+    }
+
+    domname = argv[optind];
+
+    if (libxl_name_to_domid(ctx, domname, &domid)) {
+        fprintf(stderr, "Can't get domid of domain name '%s', maybe this domain does not exist.\n", domname);
+        return EXIT_FAILURE;
+    }
+
+    printf("%u\n", domid);
+
+    return EXIT_SUCCESS;
+}
+
+int main_domname(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    char *domname = NULL;
+    char *endptr = NULL;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "domname", 1) {
+        /* No options */
+    }
+
+    domid = strtol(argv[optind], &endptr, 10);
+    if (domid == 0 && !strcmp(endptr, argv[optind])) {
+        /*no digits at all*/
+        fprintf(stderr, "Invalid domain id.\n\n");
+        return EXIT_FAILURE;
+    }
+
+    domname = libxl_domid_to_name(ctx, domid);
+    if (!domname) {
+        fprintf(stderr, "Can't get domain name of domain id '%u', maybe this domain does not exist.\n", domid);
+        return EXIT_FAILURE;
+    }
+
+    printf("%s\n", domname);
+    free(domname);
+
+    return EXIT_SUCCESS;
+}
+
+static char *uptime_to_string(unsigned long uptime, int short_mode)
+{
+    int sec, min, hour, day;
+    char *time_string;
+
+    day = (int)(uptime / 86400);
+    uptime -= (day * 86400);
+    hour = (int)(uptime / 3600);
+    uptime -= (hour * 3600);
+    min = (int)(uptime / 60);
+    uptime -= (min * 60);
+    sec = uptime;
+
+    if (short_mode)
+        if (day > 1)
+            xasprintf(&time_string, "%d days, %2d:%02d", day, hour, min);
+        else if (day == 1)
+            xasprintf(&time_string, "%d day, %2d:%02d", day, hour, min);
+        else
+            xasprintf(&time_string, "%2d:%02d", hour, min);
+    else
+        if (day > 1)
+            xasprintf(&time_string, "%d days, %2d:%02d:%02d", day, hour, min, sec);
+        else if (day == 1)
+            xasprintf(&time_string, "%d day, %2d:%02d:%02d", day, hour, min, sec);
+        else
+            xasprintf(&time_string, "%2d:%02d:%02d", hour, min, sec);
+
+    return time_string;
+}
+
+int main_claims(int argc, char **argv)
+{
+    libxl_dominfo *info;
+    int opt;
+    int nb_domain;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "claims", 0) {
+        /* No options */
+    }
+
+    if (!claim_mode)
+        fprintf(stderr, "claim_mode not enabled (see man xl.conf).\n");
+
+    info = libxl_list_domain(ctx, &nb_domain);
+    if (!info) {
+        fprintf(stderr, "libxl_list_domain failed.\n");
+        return 1;
+    }
+
+    list_domains(false /* verbose */, false /* context */, true /* claim */,
+                 false /* numa */, false /* cpupool */, info, nb_domain);
+
+    libxl_dominfo_list_free(info, nb_domain);
+    return 0;
+}
+
+static char *current_time_to_string(time_t now)
+{
+    char now_str[100];
+    struct tm *tmp;
+
+    tmp = localtime(&now);
+    if (tmp == NULL) {
+        fprintf(stderr, "Get localtime error");
+        exit(-1);
+    }
+    if (strftime(now_str, sizeof(now_str), "%H:%M:%S", tmp) == 0) {
+        fprintf(stderr, "strftime returned 0");
+        exit(-1);
+    }
+    return strdup(now_str);
+}
+
+static void print_dom0_uptime(int short_mode, time_t now)
+{
+    int fd;
+    ssize_t nr;
+    char buf[512];
+    uint32_t uptime = 0;
+    char *uptime_str = NULL;
+    char *now_str = NULL;
+    char *domname;
+
+    fd = open("/proc/uptime", O_RDONLY);
+    if (fd == -1)
+        goto err;
+
+    nr = read(fd, buf, sizeof(buf) - 1);
+    if (nr == -1) {
+        close(fd);
+        goto err;
+    }
+    close(fd);
+
+    buf[nr] = '\0';
+
+    strtok(buf, " ");
+    uptime = strtoul(buf, NULL, 10);
+
+    domname = libxl_domid_to_name(ctx, 0);
+    if (short_mode)
+    {
+        now_str = current_time_to_string(now);
+        uptime_str = uptime_to_string(uptime, 1);
+        printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
+               domname, 0);
+    }
+    else
+    {
+        now_str = NULL;
+        uptime_str = uptime_to_string(uptime, 0);
+        printf("%-33s %4d %s\n", domname,
+               0, uptime_str);
+    }
+
+    free(now_str);
+    free(uptime_str);
+    free(domname);
+    return;
+err:
+    fprintf(stderr, "Can not get Dom0 uptime.\n");
+    exit(-1);
+}
+
+static void print_domU_uptime(uint32_t domuid, int short_mode, time_t now)
+{
+    uint32_t s_time = 0;
+    uint32_t uptime = 0;
+    char *uptime_str = NULL;
+    char *now_str = NULL;
+    char *domname;
+
+    s_time = libxl_vm_get_start_time(ctx, domuid);
+    if (s_time == -1)
+        return;
+    uptime = now - s_time;
+    domname = libxl_domid_to_name(ctx, domuid);
+    if (short_mode)
+    {
+        now_str = current_time_to_string(now);
+        uptime_str = uptime_to_string(uptime, 1);
+        printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
+               domname, domuid);
+    }
+    else
+    {
+        now_str = NULL;
+        uptime_str = uptime_to_string(uptime, 0);
+        printf("%-33s %4d %s\n", domname,
+               domuid, uptime_str);
+    }
+
+    free(domname);
+    free(now_str);
+    free(uptime_str);
+    return;
+}
+
+static void print_uptime(int short_mode, uint32_t doms[], int nb_doms)
+{
+    libxl_vminfo *info;
+    time_t now;
+    int nb_vm, i;
+
+    now = time(NULL);
+
+    if (!short_mode)
+        printf("%-33s %4s %s\n", "Name", "ID", "Uptime");
+
+    if (nb_doms == 0) {
+        print_dom0_uptime(short_mode, now);
+        info = libxl_list_vm(ctx, &nb_vm);
+        if (info == NULL) {
+            fprintf(stderr, "Could not list vms.\n");
+            return;
+        }
+        for (i = 0; i < nb_vm; i++) {
+            if (info[i].domid == 0) continue;
+            print_domU_uptime(info[i].domid, short_mode, now);
+        }
+        libxl_vminfo_list_free(info, nb_vm);
+    } else {
+        for (i = 0; i < nb_doms; i++) {
+            if (doms[i] == 0)
+                print_dom0_uptime(short_mode, now);
+            else
+                print_domU_uptime(doms[i], short_mode, now);
+        }
+    }
+}
+
+int main_uptime(int argc, char **argv)
+{
+    const char *dom;
+    int short_mode = 0;
+    uint32_t domains[100];
+    int nb_doms = 0;
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "s", NULL, "uptime", 0) {
+    case 's':
+        short_mode = 1;
+        break;
+    }
+
+    for (;(dom = argv[optind]) != NULL; nb_doms++,optind++)
+        domains[nb_doms] = xfind_domain(dom);
+
+    print_uptime(short_mode, domains, nb_doms);
+
+    return 0;
+}
+
+int main_dmesg(int argc, char **argv)
+{
+    unsigned int clear = 0;
+    libxl_xen_console_reader *cr;
+    char *line;
+    int opt, ret = 1;
+
+    SWITCH_FOREACH_OPT(opt, "c", NULL, "dmesg", 0) {
+    case 'c':
+        clear = 1;
+        break;
+    }
+
+    cr = libxl_xen_console_read_start(ctx, clear);
+    if (!cr)
+        goto finish;
+
+    while ((ret = libxl_xen_console_read_line(ctx, cr, &line)) > 0)
+        printf("%s", line);
+
+finish:
+    if (cr)
+        libxl_xen_console_read_finish(ctx, cr);
+    return ret ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+int main_top(int argc, char **argv)
+{
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "top", 0) {
+        /* No options */
+    }
+
+    return system("xentop");
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 24/29] xl: split out vnc and console related code
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (22 preceding siblings ...)
  2017-02-24 16:13 ` [PATCH 23/29] xl: split out functions to print out information Wei Liu
@ 2017-02-24 16:13 ` Wei Liu
  2017-02-27 15:59   ` Ian Jackson
  2017-02-24 16:13 ` [PATCH 25/29] xl: split out miscellaneous functions Wei Liu
                   ` (4 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:13 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

The new file also contains code for channel, which is just a console
in disguise.

Replace the call to vncviewer() with libxl_vncviewer_exec() directly in
main_vncviewer.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   2 +-
 tools/xl/xl_cmdimpl.c |  98 -------------------------------------
 tools/xl/xl_console.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 131 insertions(+), 99 deletions(-)
 create mode 100644 tools/xl/xl_console.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index c51106e49e..b49e2cdcab 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -19,7 +19,7 @@ XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
 XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
 XL_OBJS += xl_vtpm.o xl_block.o xl_nic.o xl_usb.o
 XL_OBJS += xl_sched.o xl_pci.o xl_vcpu.o xl_cd.o xl_mem.o
-XL_OBJS += xl_psr.o xl_info.o
+XL_OBJS += xl_psr.o xl_info.o xl_console.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index 1de5445e7f..d32e7fe6f1 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -1071,60 +1071,6 @@ void help(const char *command)
     }
 }
 
-int main_console(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt = 0, num = 0;
-    libxl_console_type type = 0;
-
-    SWITCH_FOREACH_OPT(opt, "n:t:", NULL, "console", 1) {
-    case 't':
-        if (!strcmp(optarg, "pv"))
-            type = LIBXL_CONSOLE_TYPE_PV;
-        else if (!strcmp(optarg, "serial"))
-            type = LIBXL_CONSOLE_TYPE_SERIAL;
-        else {
-            fprintf(stderr, "console type supported are: pv, serial\n");
-            return EXIT_FAILURE;
-        }
-        break;
-    case 'n':
-        num = atoi(optarg);
-        break;
-    }
-
-    domid = xfind_domain(argv[optind]);
-    if (!type)
-        libxl_primary_console_exec(ctx, domid, -1);
-    else
-        libxl_console_exec(ctx, domid, num, type, -1);
-    fprintf(stderr, "Unable to attach console\n");
-    return EXIT_FAILURE;
-}
-
-int main_vncviewer(int argc, char **argv)
-{
-    static const struct option opts[] = {
-        {"autopass", 0, 0, 'a'},
-        {"vncviewer-autopass", 0, 0, 'a'},
-        COMMON_LONG_OPTS
-    };
-    uint32_t domid;
-    int opt, autopass = 0;
-
-    SWITCH_FOREACH_OPT(opt, "a", opts, "vncviewer", 1) {
-    case 'a':
-        autopass = 1;
-        break;
-    }
-
-    domid = xfind_domain(argv[optind]);
-
-    if (vncviewer(domid, autopass))
-        return EXIT_FAILURE;
-    return EXIT_SUCCESS;
-}
-
 static void pause_domain(uint32_t domid)
 {
     libxl_domain_pause(ctx, domid);
@@ -2514,50 +2460,6 @@ int main_debug_keys(int argc, char **argv)
     return EXIT_SUCCESS;
 }
 
-int main_channellist(int argc, char **argv)
-{
-    int opt;
-    libxl_device_channel *channels;
-    libxl_channelinfo channelinfo;
-    int nb, i;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "channel-list", 1) {
-        /* No options */
-    }
-
-    /*      Idx BE state evt-ch ring-ref connection params*/
-    printf("%-3s %-2s %-5s %-6s %8s %-10s %-30s\n",
-           "Idx", "BE", "state", "evt-ch", "ring-ref", "connection", "");
-    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
-        uint32_t domid = xfind_domain(*argv);
-        channels = libxl_device_channel_list(ctx, domid, &nb);
-        if (!channels)
-            continue;
-        for (i = 0; i < nb; ++i) {
-            if (!libxl_device_channel_getinfo(ctx, domid, &channels[i],
-                &channelinfo)) {
-                printf("%-3d %-2d ", channels[i].devid, channelinfo.backend_id);
-                printf("%-5d ", channelinfo.state);
-                printf("%-6d %-8d ", channelinfo.evtch, channelinfo.rref);
-                printf("%-10s ", libxl_channel_connection_to_string(
-                       channels[i].connection));
-                switch (channels[i].connection) {
-                    case LIBXL_CHANNEL_CONNECTION_PTY:
-                        printf("%-30s ", channelinfo.u.pty.path);
-                        break;
-                    default:
-                        break;
-                }
-                printf("\n");
-                libxl_channelinfo_dispose(&channelinfo);
-            }
-            libxl_device_channel_dispose(&channels[i]);
-        }
-        free(channels);
-    }
-    return 0;
-}
-
 #ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
 int main_remus(int argc, char **argv)
 {
diff --git a/tools/xl/xl_console.c b/tools/xl/xl_console.c
new file mode 100644
index 0000000000..c3abb3f631
--- /dev/null
+++ b/tools/xl/xl_console.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <stdlib.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+int main_console(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt = 0, num = 0;
+    libxl_console_type type = 0;
+
+    SWITCH_FOREACH_OPT(opt, "n:t:", NULL, "console", 1) {
+    case 't':
+        if (!strcmp(optarg, "pv"))
+            type = LIBXL_CONSOLE_TYPE_PV;
+        else if (!strcmp(optarg, "serial"))
+            type = LIBXL_CONSOLE_TYPE_SERIAL;
+        else {
+            fprintf(stderr, "console type supported are: pv, serial\n");
+            return EXIT_FAILURE;
+        }
+        break;
+    case 'n':
+        num = atoi(optarg);
+        break;
+    }
+
+    domid = xfind_domain(argv[optind]);
+    if (!type)
+        libxl_primary_console_exec(ctx, domid, -1);
+    else
+        libxl_console_exec(ctx, domid, num, type, -1);
+    fprintf(stderr, "Unable to attach console\n");
+    return EXIT_FAILURE;
+}
+
+int main_vncviewer(int argc, char **argv)
+{
+    static const struct option opts[] = {
+        {"autopass", 0, 0, 'a'},
+        {"vncviewer-autopass", 0, 0, 'a'},
+        COMMON_LONG_OPTS
+    };
+    uint32_t domid;
+    int opt, autopass = 0;
+
+    SWITCH_FOREACH_OPT(opt, "a", opts, "vncviewer", 1) {
+    case 'a':
+        autopass = 1;
+        break;
+    }
+
+    domid = xfind_domain(argv[optind]);
+
+    libxl_vncviewer_exec(ctx, domid, autopass);
+
+    return EXIT_FAILURE;
+}
+
+/* Channel is just a console in disguise, so put it here */
+int main_channellist(int argc, char **argv)
+{
+    int opt;
+    libxl_device_channel *channels;
+    libxl_channelinfo channelinfo;
+    int nb, i;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "channel-list", 1) {
+        /* No options */
+    }
+
+    /*      Idx BE state evt-ch ring-ref connection params*/
+    printf("%-3s %-2s %-5s %-6s %8s %-10s %-30s\n",
+           "Idx", "BE", "state", "evt-ch", "ring-ref", "connection", "");
+    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
+        uint32_t domid = xfind_domain(*argv);
+        channels = libxl_device_channel_list(ctx, domid, &nb);
+        if (!channels)
+            continue;
+        for (i = 0; i < nb; ++i) {
+            if (!libxl_device_channel_getinfo(ctx, domid, &channels[i],
+                &channelinfo)) {
+                printf("%-3d %-2d ", channels[i].devid, channelinfo.backend_id);
+                printf("%-5d ", channelinfo.state);
+                printf("%-6d %-8d ", channelinfo.evtch, channelinfo.rref);
+                printf("%-10s ", libxl_channel_connection_to_string(
+                       channels[i].connection));
+                switch (channels[i].connection) {
+                    case LIBXL_CHANNEL_CONNECTION_PTY:
+                        printf("%-30s ", channelinfo.u.pty.path);
+                        break;
+                    default:
+                        break;
+                }
+                printf("\n");
+                libxl_channelinfo_dispose(&channelinfo);
+            }
+            libxl_device_channel_dispose(&channels[i]);
+        }
+        free(channels);
+    }
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 25/29] xl: split out miscellaneous functions
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (23 preceding siblings ...)
  2017-02-24 16:13 ` [PATCH 24/29] xl: split out vnc and console related code Wei Liu
@ 2017-02-24 16:13 ` Wei Liu
  2017-02-27 15:58   ` Ian Jackson
  2017-02-24 16:13 ` [PATCH 26/29] xl: split out vm lifecycle control functions Wei Liu
                   ` (3 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:13 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

A collections of functions that don't warrant their own files.

Moving main_devd there requires lifting do_daemonize to xl_utils.c.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   2 +-
 tools/xl/xl_cmdimpl.c | 390 --------------------------------------------------
 tools/xl/xl_misc.c    | 355 +++++++++++++++++++++++++++++++++++++++++++++
 tools/xl/xl_utils.c   |  70 +++++++++
 tools/xl/xl_utils.h   |   1 +
 5 files changed, 427 insertions(+), 391 deletions(-)
 create mode 100644 tools/xl/xl_misc.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index b49e2cdcab..3e8361b121 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -19,7 +19,7 @@ XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
 XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
 XL_OBJS += xl_vtpm.o xl_block.o xl_nic.o xl_usb.o
 XL_OBJS += xl_sched.o xl_pci.o xl_vcpu.o xl_cd.o xl_mem.o
-XL_OBJS += xl_psr.o xl_info.o xl_console.o
+XL_OBJS += xl_psr.o xl_info.o xl_console.o xl_misc.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index d32e7fe6f1..7851fc03d4 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -222,74 +222,6 @@ release_lock:
     return rc;
 }
 
-static int do_daemonize(char *name, const char *pidfile)
-{
-    char *fullname;
-    pid_t child1;
-    int nullfd, ret = 0;
-
-    child1 = xl_fork(child_waitdaemon, "domain monitoring daemonizing child");
-    if (child1) {
-        ret = child_report(child_waitdaemon);
-        if (ret) goto out;
-        ret = 1;
-        goto out;
-    }
-
-    postfork();
-
-    ret = libxl_create_logfile(ctx, name, &fullname);
-    if (ret) {
-        LOG("failed to open logfile %s: %s",fullname,strerror(errno));
-        exit(-1);
-    }
-
-    CHK_SYSCALL(logfile = open(fullname, O_WRONLY|O_CREAT|O_APPEND, 0644));
-    free(fullname);
-    assert(logfile >= 3);
-
-    CHK_SYSCALL(nullfd = open("/dev/null", O_RDONLY));
-    assert(nullfd >= 3);
-
-    dup2(nullfd, 0);
-    dup2(logfile, 1);
-    dup2(logfile, 2);
-
-    close(nullfd);
-
-    CHK_SYSCALL(daemon(0, 1));
-
-    if (pidfile) {
-        int fd = open(pidfile, O_RDWR | O_CREAT, S_IRUSR|S_IWUSR);
-        char *pid = NULL;
-
-        if (fd == -1) {
-            perror("Unable to open pidfile");
-            exit(1);
-        }
-
-        if (asprintf(&pid, "%ld\n", (long)getpid()) == -1) {
-            perror("Formatting pid");
-            exit(1);
-        }
-
-        if (write(fd, pid, strlen(pid)) < 0) {
-            perror("Writing pid");
-            exit(1);
-        }
-
-        if (close(fd) < 0) {
-            perror("Closing pidfile");
-            exit(1);
-        }
-
-        free(pid);
-    }
-
-out:
-    return ret;
-}
-
 static void reload_domain_config(uint32_t domid,
                                  libxl_domain_config *d_config)
 {
@@ -1192,14 +1124,6 @@ static void reboot_domain(uint32_t domid, libxl_evgen_domain_death **deathw,
     }
 }
 
-static void core_dump_domain(uint32_t domid, const char *filename)
-{
-    int rc;
-
-    rc=libxl_domain_core_dump(ctx, domid, filename, NULL);
-    if (rc) { fprintf(stderr,"core dump failed (rc=%d)\n",rc);exit(EXIT_FAILURE); }
-}
-
 #ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
 static void save_domain_core_begin(uint32_t domid,
                                    const char *override_config_file,
@@ -1991,18 +1915,6 @@ int main_migrate(int argc, char **argv)
 }
 #endif
 
-int main_dump_core(int argc, char **argv)
-{
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "dump-core", 2) {
-        /* No options */
-    }
-
-    core_dump_domain(xfind_domain(argv[optind]), argv[optind + 1]);
-    return EXIT_SUCCESS;
-}
-
 int main_pause(int argc, char **argv)
 {
     int opt;
@@ -2220,246 +2132,6 @@ int main_create(int argc, char **argv)
     return 0;
 }
 
-extern void printf_info(enum output_format output_format,
-                        int domid,
-                        libxl_domain_config *d_config, FILE *fh);
-int main_config_update(int argc, char **argv)
-{
-    uint32_t domid;
-    const char *filename = NULL;
-    char *extra_config = NULL;
-    void *config_data = 0;
-    int config_len = 0;
-    libxl_domain_config d_config;
-    int opt, rc;
-    int debug = 0;
-    static struct option opts[] = {
-        {"defconfig", 1, 0, 'f'},
-        COMMON_LONG_OPTS
-    };
-
-    if (argc < 2) {
-        fprintf(stderr, "xl config-update requires a domain argument\n");
-        help("config-update");
-        exit(1);
-    }
-
-    fprintf(stderr, "WARNING: xl now has better capability to manage domain configuration, "
-            "avoid using this command when possible\n");
-
-    domid = xfind_domain(argv[1]);
-    argc--; argv++;
-
-    if (argv[1] && argv[1][0] != '-' && !strchr(argv[1], '=')) {
-        filename = argv[1];
-        argc--; argv++;
-    }
-
-    SWITCH_FOREACH_OPT(opt, "dqf:", opts, "config_update", 0) {
-    case 'd':
-        debug = 1;
-        break;
-    case 'f':
-        filename = optarg;
-        break;
-    }
-
-    for (; optind < argc; optind++) {
-        if (strchr(argv[optind], '=') != NULL) {
-            xstring_realloc_append(&extra_config, argv[optind]);
-            xstring_realloc_append(&extra_config, "\n");
-        } else if (!filename) {
-            filename = argv[optind];
-        } else {
-            help("create");
-            free(extra_config);
-            return 2;
-        }
-    }
-    if (filename) {
-        free(config_data);  config_data = 0;
-        rc = libxl_read_file_contents(ctx, filename,
-                                      &config_data, &config_len);
-        if (rc) { fprintf(stderr, "Failed to read config file: %s: %s\n",
-                           filename, strerror(errno));
-                  free(extra_config); return ERROR_FAIL; }
-        if (extra_config && strlen(extra_config)) {
-            if (config_len > INT_MAX - (strlen(extra_config) + 2 + 1)) {
-                fprintf(stderr, "Failed to attach extra configuration\n");
-                exit(1);
-            }
-            /* allocate space for the extra config plus two EOLs plus \0 */
-            config_data = realloc(config_data, config_len
-                + strlen(extra_config) + 2 + 1);
-            if (!config_data) {
-                fprintf(stderr, "Failed to realloc config_data\n");
-                exit(1);
-            }
-            config_len += sprintf(config_data + config_len, "\n%s\n",
-                extra_config);
-        }
-    } else {
-        fprintf(stderr, "Config file not specified\n");
-        exit(1);
-    }
-
-    libxl_domain_config_init(&d_config);
-
-    parse_config_data(filename, config_data, config_len, &d_config);
-
-    if (debug || dryrun_only)
-        printf_info(default_output_format, -1, &d_config, stdout);
-
-    if (!dryrun_only) {
-        fprintf(stderr, "setting dom%u configuration\n", domid);
-        rc = libxl_userdata_store(ctx, domid, "xl",
-                                   config_data, config_len);
-        if (rc) {
-            fprintf(stderr, "failed to update configuration\n");
-            exit(1);
-        }
-    }
-
-    libxl_domain_config_dispose(&d_config);
-
-    free(config_data);
-    free(extra_config);
-    return 0;
-}
-
-static void button_press(uint32_t domid, const char *b)
-{
-    libxl_trigger trigger;
-
-    if (!strcmp(b, "power")) {
-        trigger = LIBXL_TRIGGER_POWER;
-    } else if (!strcmp(b, "sleep")) {
-        trigger = LIBXL_TRIGGER_SLEEP;
-    } else {
-        fprintf(stderr, "%s is an invalid button identifier\n", b);
-        exit(EXIT_FAILURE);
-    }
-
-    libxl_send_trigger(ctx, domid, trigger, 0);
-}
-
-int main_button_press(int argc, char **argv)
-{
-    int opt;
-
-    fprintf(stderr, "WARNING: \"button-press\" is deprecated. "
-            "Please use \"trigger\"\n");
-
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "button-press", 2) {
-        /* No options */
-    }
-
-    button_press(xfind_domain(argv[optind]), argv[optind + 1]);
-
-    return 0;
-}
-
-int main_rename(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    const char *dom, *new_name;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "rename", 2) {
-        /* No options */
-    }
-
-    dom = argv[optind++];
-    new_name = argv[optind];
-
-    domid = xfind_domain(dom);
-    if (libxl_domain_rename(ctx, domid, common_domname, new_name)) {
-        fprintf(stderr, "Can't rename domain '%s'.\n", dom);
-        return 1;
-    }
-
-    return 0;
-}
-
-int main_trigger(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    char *endptr = NULL;
-    int vcpuid = 0;
-    const char *trigger_name = NULL;
-    libxl_trigger trigger;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "trigger", 2) {
-        /* No options */
-    }
-
-    domid = xfind_domain(argv[optind++]);
-
-    trigger_name = argv[optind++];
-    if (libxl_trigger_from_string(trigger_name, &trigger)) {
-        fprintf(stderr, "Invalid trigger \"%s\"\n", trigger_name);
-        return EXIT_FAILURE;
-    }
-
-    if (argv[optind]) {
-        vcpuid = strtol(argv[optind], &endptr, 10);
-        if (vcpuid == 0 && !strcmp(endptr, argv[optind])) {
-            fprintf(stderr, "Invalid vcpuid, using default vcpuid=0.\n\n");
-        }
-    }
-
-    libxl_send_trigger(ctx, domid, trigger, vcpuid);
-
-    return EXIT_SUCCESS;
-}
-
-
-int main_sysrq(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt;
-    const char *sysrq = NULL;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "sysrq", 2) {
-        /* No options */
-    }
-
-    domid = xfind_domain(argv[optind++]);
-
-    sysrq = argv[optind];
-
-    if (sysrq[1] != '\0') {
-        fprintf(stderr, "Invalid sysrq.\n\n");
-        help("sysrq");
-        return EXIT_FAILURE;
-    }
-
-    libxl_send_sysrq(ctx, domid, sysrq[0]);
-
-    return EXIT_SUCCESS;
-}
-
-int main_debug_keys(int argc, char **argv)
-{
-    int opt;
-    char *keys;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "debug-keys", 1) {
-        /* No options */
-    }
-
-    keys = argv[optind];
-
-    if (libxl_send_debug_keys(ctx, keys)) {
-        fprintf(stderr, "cannot send debug keys: %s\n", keys);
-        return EXIT_FAILURE;
-    }
-
-    return EXIT_SUCCESS;
-}
-
 #ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
 int main_remus(int argc, char **argv)
 {
@@ -2611,68 +2283,6 @@ int main_remus(int argc, char **argv)
 }
 #endif
 
-int main_devd(int argc, char **argv)
-{
-    int ret = 0, opt = 0, daemonize = 1;
-    const char *pidfile = NULL;
-    static const struct option opts[] = {
-        {"pidfile", 1, 0, 'p'},
-        COMMON_LONG_OPTS,
-        {0, 0, 0, 0}
-    };
-
-    SWITCH_FOREACH_OPT(opt, "Fp:", opts, "devd", 0) {
-    case 'F':
-        daemonize = 0;
-        break;
-    case 'p':
-        pidfile = optarg;
-        break;
-    }
-
-    if (daemonize) {
-        ret = do_daemonize("xldevd", pidfile);
-        if (ret) {
-            ret = (ret == 1) ? 0 : ret;
-            goto out;
-        }
-    }
-
-    libxl_device_events_handler(ctx, 0);
-
-out:
-    return ret;
-}
-
-int main_qemu_monitor_command(int argc, char **argv)
-{
-    int opt;
-    uint32_t domid;
-    char *cmd;
-    char *output;
-    int ret;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "qemu-monitor-command", 2) {
-        /* No options */
-    }
-
-    domid = xfind_domain(argv[optind]);
-    cmd = argv[optind + 1];
-
-    if (argc - optind > 2) {
-        fprintf(stderr, "Invalid arguments.\n");
-        return EXIT_FAILURE;
-    }
-
-    ret = libxl_qemu_monitor_command(ctx, domid, cmd, &output);
-    if (!ret && output) {
-        printf("%s\n", output);
-        free(output);
-    }
-
-    return ret ? EXIT_FAILURE : EXIT_SUCCESS;
-}
-
 /*
  * Local variables:
  * mode: C
diff --git a/tools/xl/xl_misc.c b/tools/xl/xl_misc.c
new file mode 100644
index 0000000000..0bf337d8f7
--- /dev/null
+++ b/tools/xl/xl_misc.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <limits.h>
+#include <stdlib.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+extern const char *common_domname;
+
+static void button_press(uint32_t domid, const char *b)
+{
+    libxl_trigger trigger;
+
+    if (!strcmp(b, "power")) {
+        trigger = LIBXL_TRIGGER_POWER;
+    } else if (!strcmp(b, "sleep")) {
+        trigger = LIBXL_TRIGGER_SLEEP;
+    } else {
+        fprintf(stderr, "%s is an invalid button identifier\n", b);
+        exit(EXIT_FAILURE);
+    }
+
+    libxl_send_trigger(ctx, domid, trigger, 0);
+}
+
+int main_button_press(int argc, char **argv)
+{
+    int opt;
+
+    fprintf(stderr, "WARNING: \"button-press\" is deprecated. "
+            "Please use \"trigger\"\n");
+
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "button-press", 2) {
+        /* No options */
+    }
+
+    button_press(xfind_domain(argv[optind]), argv[optind + 1]);
+
+    return 0;
+}
+
+int main_rename(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    const char *dom, *new_name;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "rename", 2) {
+        /* No options */
+    }
+
+    dom = argv[optind++];
+    new_name = argv[optind];
+
+    domid = xfind_domain(dom);
+    if (libxl_domain_rename(ctx, domid, common_domname, new_name)) {
+        fprintf(stderr, "Can't rename domain '%s'.\n", dom);
+        return 1;
+    }
+
+    return 0;
+}
+
+int main_trigger(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    char *endptr = NULL;
+    int vcpuid = 0;
+    const char *trigger_name = NULL;
+    libxl_trigger trigger;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "trigger", 2) {
+        /* No options */
+    }
+
+    domid = xfind_domain(argv[optind++]);
+
+    trigger_name = argv[optind++];
+    if (libxl_trigger_from_string(trigger_name, &trigger)) {
+        fprintf(stderr, "Invalid trigger \"%s\"\n", trigger_name);
+        return EXIT_FAILURE;
+    }
+
+    if (argv[optind]) {
+        vcpuid = strtol(argv[optind], &endptr, 10);
+        if (vcpuid == 0 && !strcmp(endptr, argv[optind])) {
+            fprintf(stderr, "Invalid vcpuid, using default vcpuid=0.\n\n");
+        }
+    }
+
+    libxl_send_trigger(ctx, domid, trigger, vcpuid);
+
+    return EXIT_SUCCESS;
+}
+
+int main_sysrq(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    const char *sysrq = NULL;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "sysrq", 2) {
+        /* No options */
+    }
+
+    domid = xfind_domain(argv[optind++]);
+
+    sysrq = argv[optind];
+
+    if (sysrq[1] != '\0') {
+        fprintf(stderr, "Invalid sysrq.\n\n");
+        help("sysrq");
+        return EXIT_FAILURE;
+    }
+
+    libxl_send_sysrq(ctx, domid, sysrq[0]);
+
+    return EXIT_SUCCESS;
+}
+
+int main_debug_keys(int argc, char **argv)
+{
+    int opt;
+    char *keys;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "debug-keys", 1) {
+        /* No options */
+    }
+
+    keys = argv[optind];
+
+    if (libxl_send_debug_keys(ctx, keys)) {
+        fprintf(stderr, "cannot send debug keys: %s\n", keys);
+        return EXIT_FAILURE;
+    }
+
+    return EXIT_SUCCESS;
+}
+
+int main_devd(int argc, char **argv)
+{
+    int ret = 0, opt = 0, daemonize = 1;
+    const char *pidfile = NULL;
+    static const struct option opts[] = {
+        {"pidfile", 1, 0, 'p'},
+        COMMON_LONG_OPTS,
+        {0, 0, 0, 0}
+    };
+
+    SWITCH_FOREACH_OPT(opt, "Fp:", opts, "devd", 0) {
+    case 'F':
+        daemonize = 0;
+        break;
+    case 'p':
+        pidfile = optarg;
+        break;
+    }
+
+    if (daemonize) {
+        ret = do_daemonize("xldevd", pidfile);
+        if (ret) {
+            ret = (ret == 1) ? 0 : ret;
+            goto out;
+        }
+    }
+
+    libxl_device_events_handler(ctx, 0);
+
+out:
+    return ret;
+}
+
+int main_qemu_monitor_command(int argc, char **argv)
+{
+    int opt;
+    uint32_t domid;
+    char *cmd;
+    char *output;
+    int ret;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "qemu-monitor-command", 2) {
+        /* No options */
+    }
+
+    domid = xfind_domain(argv[optind]);
+    cmd = argv[optind + 1];
+
+    if (argc - optind > 2) {
+        fprintf(stderr, "Invalid arguments.\n");
+        return EXIT_FAILURE;
+    }
+
+    ret = libxl_qemu_monitor_command(ctx, domid, cmd, &output);
+    if (!ret && output) {
+        printf("%s\n", output);
+        free(output);
+    }
+
+    return ret ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+static void core_dump_domain(uint32_t domid, const char *filename)
+{
+    int rc;
+
+    rc=libxl_domain_core_dump(ctx, domid, filename, NULL);
+    if (rc) { fprintf(stderr,"core dump failed (rc=%d)\n",rc);exit(EXIT_FAILURE); }
+}
+
+int main_dump_core(int argc, char **argv)
+{
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "dump-core", 2) {
+        /* No options */
+    }
+
+    core_dump_domain(xfind_domain(argv[optind]), argv[optind + 1]);
+    return EXIT_SUCCESS;
+}
+
+extern void printf_info(enum output_format output_format,
+                        int domid,
+                        libxl_domain_config *d_config, FILE *fh);
+int main_config_update(int argc, char **argv)
+{
+    uint32_t domid;
+    const char *filename = NULL;
+    char *extra_config = NULL;
+    void *config_data = 0;
+    int config_len = 0;
+    libxl_domain_config d_config;
+    int opt, rc;
+    int debug = 0;
+    static struct option opts[] = {
+        {"defconfig", 1, 0, 'f'},
+        COMMON_LONG_OPTS
+    };
+
+    if (argc < 2) {
+        fprintf(stderr, "xl config-update requires a domain argument\n");
+        help("config-update");
+        exit(1);
+    }
+
+    fprintf(stderr, "WARNING: xl now has better capability to manage domain configuration, "
+            "avoid using this command when possible\n");
+
+    domid = xfind_domain(argv[1]);
+    argc--; argv++;
+
+    if (argv[1] && argv[1][0] != '-' && !strchr(argv[1], '=')) {
+        filename = argv[1];
+        argc--; argv++;
+    }
+
+    SWITCH_FOREACH_OPT(opt, "dqf:", opts, "config_update", 0) {
+    case 'd':
+        debug = 1;
+        break;
+    case 'f':
+        filename = optarg;
+        break;
+    }
+
+    for (; optind < argc; optind++) {
+        if (strchr(argv[optind], '=') != NULL) {
+            xstring_realloc_append(&extra_config, argv[optind]);
+            xstring_realloc_append(&extra_config, "\n");
+        } else if (!filename) {
+            filename = argv[optind];
+        } else {
+            help("create");
+            free(extra_config);
+            return 2;
+        }
+    }
+    if (filename) {
+        free(config_data);  config_data = 0;
+        rc = libxl_read_file_contents(ctx, filename,
+                                      &config_data, &config_len);
+        if (rc) { fprintf(stderr, "Failed to read config file: %s: %s\n",
+                           filename, strerror(errno));
+                  free(extra_config); return ERROR_FAIL; }
+        if (extra_config && strlen(extra_config)) {
+            if (config_len > INT_MAX - (strlen(extra_config) + 2 + 1)) {
+                fprintf(stderr, "Failed to attach extra configuration\n");
+                exit(1);
+            }
+            /* allocate space for the extra config plus two EOLs plus \0 */
+            config_data = realloc(config_data, config_len
+                + strlen(extra_config) + 2 + 1);
+            if (!config_data) {
+                fprintf(stderr, "Failed to realloc config_data\n");
+                exit(1);
+            }
+            config_len += sprintf(config_data + config_len, "\n%s\n",
+                extra_config);
+        }
+    } else {
+        fprintf(stderr, "Config file not specified\n");
+        exit(1);
+    }
+
+    libxl_domain_config_init(&d_config);
+
+    parse_config_data(filename, config_data, config_len, &d_config);
+
+    if (debug || dryrun_only)
+        printf_info(default_output_format, -1, &d_config, stdout);
+
+    if (!dryrun_only) {
+        fprintf(stderr, "setting dom%u configuration\n", domid);
+        rc = libxl_userdata_store(ctx, domid, "xl",
+                                   config_data, config_len);
+        if (rc) {
+            fprintf(stderr, "failed to update configuration\n");
+            exit(1);
+        }
+    }
+
+    libxl_domain_config_dispose(&d_config);
+
+    free(config_data);
+    free(extra_config);
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/xl/xl_utils.c b/tools/xl/xl_utils.c
index e0b4cb2547..e3ae1b8bf5 100644
--- a/tools/xl/xl_utils.c
+++ b/tools/xl/xl_utils.c
@@ -14,8 +14,11 @@
 
 #define _GNU_SOURCE
 
+#include <fcntl.h>
 #include <limits.h>
 #include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include <unistd.h>
 
 #include <libxl.h>
@@ -248,6 +251,73 @@ void print_bitmap(uint8_t *map, int maplen, FILE *stream)
     }
 }
 
+int do_daemonize(char *name, const char *pidfile)
+{
+    char *fullname;
+    pid_t child1;
+    int nullfd, ret = 0;
+
+    child1 = xl_fork(child_waitdaemon, "domain monitoring daemonizing child");
+    if (child1) {
+        ret = child_report(child_waitdaemon);
+        if (ret) goto out;
+        ret = 1;
+        goto out;
+    }
+
+    postfork();
+
+    ret = libxl_create_logfile(ctx, name, &fullname);
+    if (ret) {
+        LOG("failed to open logfile %s: %s",fullname,strerror(errno));
+        exit(-1);
+    }
+
+    CHK_SYSCALL(logfile = open(fullname, O_WRONLY|O_CREAT|O_APPEND, 0644));
+    free(fullname);
+    assert(logfile >= 3);
+
+    CHK_SYSCALL(nullfd = open("/dev/null", O_RDONLY));
+    assert(nullfd >= 3);
+
+    dup2(nullfd, 0);
+    dup2(logfile, 1);
+    dup2(logfile, 2);
+
+    close(nullfd);
+
+    CHK_SYSCALL(daemon(0, 1));
+
+    if (pidfile) {
+        int fd = open(pidfile, O_RDWR | O_CREAT, S_IRUSR|S_IWUSR);
+        char *pid = NULL;
+
+        if (fd == -1) {
+            perror("Unable to open pidfile");
+            exit(1);
+        }
+
+        if (asprintf(&pid, "%ld\n", (long)getpid()) == -1) {
+            perror("Formatting pid");
+            exit(1);
+        }
+
+        if (write(fd, pid, strlen(pid)) < 0) {
+            perror("Writing pid");
+            exit(1);
+        }
+
+        if (close(fd) < 0) {
+            perror("Closing pidfile");
+            exit(1);
+        }
+
+        free(pid);
+    }
+
+out:
+    return ret;
+}
 
 /*
  * Local variables:
diff --git a/tools/xl/xl_utils.h b/tools/xl/xl_utils.h
index 2786f7c3cd..a159287f5e 100644
--- a/tools/xl/xl_utils.h
+++ b/tools/xl/xl_utils.h
@@ -145,6 +145,7 @@ uint32_t xfind_domain(const char *p) __attribute__((warn_unused_result));
 
 void print_bitmap(uint8_t *map, int maplen, FILE *stream);
 
+int do_daemonize(char *name, const char *pidfile);
 #endif /* XL_UTILS_H */
 
 /*
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 26/29] xl: split out vm lifecycle control functions
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (24 preceding siblings ...)
  2017-02-24 16:13 ` [PATCH 25/29] xl: split out miscellaneous functions Wei Liu
@ 2017-02-24 16:13 ` Wei Liu
  2017-02-27 16:00   ` Ian Jackson
  2017-02-24 16:13 ` [PATCH 27/29] xl: split out save/restore related code Wei Liu
                   ` (2 subsequent siblings)
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:13 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Including create, reboot, shutdown, pause, unpause and destroy.

Lift a bunch of core data structures and function declarations to xl.h
because they are needed in both xl_cmdimpl.c and xl_vmcontrol.c.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile       |    1 +
 tools/xl/xl.h           |   67 +++
 tools/xl/xl_cmdimpl.c   | 1243 -----------------------------------------------
 tools/xl/xl_vmcontrol.c | 1225 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 1293 insertions(+), 1243 deletions(-)
 create mode 100644 tools/xl/xl_vmcontrol.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index 3e8361b121..0f966684be 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -20,6 +20,7 @@ XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
 XL_OBJS += xl_vtpm.o xl_block.o xl_nic.o xl_usb.o
 XL_OBJS += xl_sched.o xl_pci.o xl_vcpu.o xl_cd.o xl_mem.o
 XL_OBJS += xl_psr.o xl_info.o xl_console.o xl_misc.o
+XL_OBJS += xl_vmcontrol.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl.h b/tools/xl/xl.h
index a8b6264c59..62d010076b 100644
--- a/tools/xl/xl.h
+++ b/tools/xl/xl.h
@@ -30,6 +30,73 @@ struct cmd_spec {
     char *cmd_option;
 };
 
+struct domain_create {
+    int debug;
+    int daemonize;
+    int monitor; /* handle guest reboots etc */
+    int paused;
+    int dryrun;
+    int quiet;
+    int vnc;
+    int vncautopass;
+    int console_autoconnect;
+    int checkpointed_stream;
+    const char *config_file;
+    char *extra_config; /* extra config string */
+    const char *restore_file;
+    char *colo_proxy_script;
+    int migrate_fd; /* -1 means none */
+    int send_back_fd; /* -1 means none */
+    char **migration_domname_r; /* from malloc */
+};
+
+int create_domain(struct domain_create *dom_info);
+
+
+static const char savefileheader_magic[32]=
+    "Xen saved domain, xl format\n \0 \r";
+
+#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
+static const char migrate_receiver_banner[]=
+    "xl migration receiver ready, send binary domain data.\n";
+static const char migrate_receiver_ready[]=
+    "domain received, ready to unpause";
+static const char migrate_permission_to_go[]=
+    "domain is yours, you are cleared to unpause";
+static const char migrate_report[]=
+    "my copy unpause results are as follows";
+#endif
+
+  /* followed by one byte:
+   *     0: everything went well, domain is running
+   *            next thing is we all exit
+   * non-0: things went badly
+   *            next thing should be a migrate_permission_to_go
+   *            from target to source
+   */
+
+#define XL_MANDATORY_FLAG_JSON (1U << 0) /* config data is in JSON format */
+#define XL_MANDATORY_FLAG_STREAMv2 (1U << 1) /* stream is v2 */
+#define XL_MANDATORY_FLAG_ALL  (XL_MANDATORY_FLAG_JSON |        \
+                                XL_MANDATORY_FLAG_STREAMv2)
+
+struct save_file_header {
+    char magic[32]; /* savefileheader_magic */
+    /* All uint32_ts are in domain's byte order. */
+    uint32_t byteorder; /* SAVEFILE_BYTEORDER_VALUE */
+    uint32_t mandatory_flags; /* unknown flags => reject restore */
+    uint32_t optional_flags; /* unknown flags => reject restore */
+    uint32_t optional_data_len; /* skip, or skip tail, if not understood */
+};
+
+/* Optional data, in order:
+ *   4 bytes uint32_t  config file size
+ *   n bytes           config file in Unix text file format
+ */
+
+#define SAVEFILE_BYTEORDER_VALUE ((uint32_t)0x01020304UL)
+
+
 /*
  * The xl process should always return either EXIT_SUCCESS or
  * EXIT_FAILURE. main_* functions, implementing the various xl
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index 7851fc03d4..b3a17d5fa6 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -49,70 +49,6 @@ libxl_ctx *ctx;
 xlchild children[child_max];
 
 const char *common_domname;
-static int fd_lock = -1;
-
-static const char savefileheader_magic[32]=
-    "Xen saved domain, xl format\n \0 \r";
-
-#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
-static const char migrate_receiver_banner[]=
-    "xl migration receiver ready, send binary domain data.\n";
-static const char migrate_receiver_ready[]=
-    "domain received, ready to unpause";
-static const char migrate_permission_to_go[]=
-    "domain is yours, you are cleared to unpause";
-static const char migrate_report[]=
-    "my copy unpause results are as follows";
-#endif
-
-  /* followed by one byte:
-   *     0: everything went well, domain is running
-   *            next thing is we all exit
-   * non-0: things went badly
-   *            next thing should be a migrate_permission_to_go
-   *            from target to source
-   */
-
-#define XL_MANDATORY_FLAG_JSON (1U << 0) /* config data is in JSON format */
-#define XL_MANDATORY_FLAG_STREAMv2 (1U << 1) /* stream is v2 */
-#define XL_MANDATORY_FLAG_ALL  (XL_MANDATORY_FLAG_JSON |        \
-                                XL_MANDATORY_FLAG_STREAMv2)
-
-struct save_file_header {
-    char magic[32]; /* savefileheader_magic */
-    /* All uint32_ts are in domain's byte order. */
-    uint32_t byteorder; /* SAVEFILE_BYTEORDER_VALUE */
-    uint32_t mandatory_flags; /* unknown flags => reject restore */
-    uint32_t optional_flags; /* unknown flags => reject restore */
-    uint32_t optional_data_len; /* skip, or skip tail, if not understood */
-};
-
-/* Optional data, in order:
- *   4 bytes uint32_t  config file size
- *   n bytes           config file in Unix text file format
- */
-
-#define SAVEFILE_BYTEORDER_VALUE ((uint32_t)0x01020304UL)
-
-struct domain_create {
-    int debug;
-    int daemonize;
-    int monitor; /* handle guest reboots etc */
-    int paused;
-    int dryrun;
-    int quiet;
-    int vnc;
-    int vncautopass;
-    int console_autoconnect;
-    int checkpointed_stream;
-    const char *config_file;
-    char *extra_config; /* extra config string */
-    const char *restore_file;
-    char *colo_proxy_script;
-    int migrate_fd; /* -1 means none */
-    int send_back_fd; /* -1 means none */
-    char **migration_domname_r; /* from malloc */
-};
 
 int child_report(xlchildnum child)
 {
@@ -130,847 +66,6 @@ int child_report(xlchildnum child)
     }
 }
 
-static void console_child_report(xlchildnum child)
-{
-    if (xl_child_pid(child))
-        child_report(child);
-}
-
-static int vncviewer(uint32_t domid, int autopass)
-{
-    libxl_vncviewer_exec(ctx, domid, autopass);
-    fprintf(stderr, "Unable to execute vncviewer\n");
-    return 1;
-}
-
-static void autoconnect_vncviewer(uint32_t domid, int autopass)
-{
-   console_child_report(child_vncviewer);
-
-    pid_t pid = xl_fork(child_vncviewer, "vncviewer child");
-    if (pid)
-        return;
-
-    postfork();
-
-    sleep(1);
-    vncviewer(domid, autopass);
-    _exit(EXIT_FAILURE);
-}
-
-static int acquire_lock(void)
-{
-    int rc;
-    struct flock fl;
-
-    /* lock already acquired */
-    if (fd_lock >= 0)
-        return ERROR_INVAL;
-
-    fl.l_type = F_WRLCK;
-    fl.l_whence = SEEK_SET;
-    fl.l_start = 0;
-    fl.l_len = 0;
-    fd_lock = open(lockfile, O_WRONLY|O_CREAT, S_IWUSR);
-    if (fd_lock < 0) {
-        fprintf(stderr, "cannot open the lockfile %s errno=%d\n", lockfile, errno);
-        return ERROR_FAIL;
-    }
-    if (fcntl(fd_lock, F_SETFD, FD_CLOEXEC) < 0) {
-        close(fd_lock);
-        fprintf(stderr, "cannot set cloexec to lockfile %s errno=%d\n", lockfile, errno);
-        return ERROR_FAIL;
-    }
-get_lock:
-    rc = fcntl(fd_lock, F_SETLKW, &fl);
-    if (rc < 0 && errno == EINTR)
-        goto get_lock;
-    if (rc < 0) {
-        fprintf(stderr, "cannot acquire lock %s errno=%d\n", lockfile, errno);
-        rc = ERROR_FAIL;
-    } else
-        rc = 0;
-    return rc;
-}
-
-static int release_lock(void)
-{
-    int rc;
-    struct flock fl;
-
-    /* lock not acquired */
-    if (fd_lock < 0)
-        return ERROR_INVAL;
-
-release_lock:
-    fl.l_type = F_UNLCK;
-    fl.l_whence = SEEK_SET;
-    fl.l_start = 0;
-    fl.l_len = 0;
-
-    rc = fcntl(fd_lock, F_SETLKW, &fl);
-    if (rc < 0 && errno == EINTR)
-        goto release_lock;
-    if (rc < 0) {
-        fprintf(stderr, "cannot release lock %s, errno=%d\n", lockfile, errno);
-        rc = ERROR_FAIL;
-    } else
-        rc = 0;
-    close(fd_lock);
-    fd_lock = -1;
-
-    return rc;
-}
-
-static void reload_domain_config(uint32_t domid,
-                                 libxl_domain_config *d_config)
-{
-    int rc;
-    uint8_t *t_data;
-    int ret, t_len;
-    libxl_domain_config d_config_new;
-
-    /* In case user has used "config-update" to store a new config
-     * file.
-     */
-    ret = libxl_userdata_retrieve(ctx, domid, "xl", &t_data, &t_len);
-    if (ret && errno != ENOENT) {
-        LOG("\"xl\" configuration found but failed to load\n");
-    }
-    if (t_len > 0) {
-        LOG("\"xl\" configuration found, using it\n");
-        libxl_domain_config_dispose(d_config);
-        libxl_domain_config_init(d_config);
-        parse_config_data("<updated>", (const char *)t_data,
-                          t_len, d_config);
-        free(t_data);
-        libxl_userdata_unlink(ctx, domid, "xl");
-        return;
-    }
-
-    libxl_domain_config_init(&d_config_new);
-    rc = libxl_retrieve_domain_configuration(ctx, domid, &d_config_new);
-    if (rc) {
-        LOG("failed to retrieve guest configuration (rc=%d). "
-            "reusing old configuration", rc);
-        libxl_domain_config_dispose(&d_config_new);
-    } else {
-        libxl_domain_config_dispose(d_config);
-        /* Steal allocations */
-        memcpy(d_config, &d_config_new, sizeof(libxl_domain_config));
-    }
-}
-
-/* Can update r_domid if domain is destroyed */
-static domain_restart_type handle_domain_death(uint32_t *r_domid,
-                                               libxl_event *event,
-                                               libxl_domain_config *d_config)
-{
-    domain_restart_type restart = DOMAIN_RESTART_NONE;
-    libxl_action_on_shutdown action;
-
-    switch (event->u.domain_shutdown.shutdown_reason) {
-    case LIBXL_SHUTDOWN_REASON_POWEROFF:
-        action = d_config->on_poweroff;
-        break;
-    case LIBXL_SHUTDOWN_REASON_REBOOT:
-        action = d_config->on_reboot;
-        break;
-    case LIBXL_SHUTDOWN_REASON_SUSPEND:
-        LOG("Domain has suspended.");
-        return 0;
-    case LIBXL_SHUTDOWN_REASON_CRASH:
-        action = d_config->on_crash;
-        break;
-    case LIBXL_SHUTDOWN_REASON_WATCHDOG:
-        action = d_config->on_watchdog;
-        break;
-    case LIBXL_SHUTDOWN_REASON_SOFT_RESET:
-        action = d_config->on_soft_reset;
-        break;
-    default:
-        LOG("Unknown shutdown reason code %d. Destroying domain.",
-            event->u.domain_shutdown.shutdown_reason);
-        action = LIBXL_ACTION_ON_SHUTDOWN_DESTROY;
-    }
-
-    LOG("Action for shutdown reason code %d is %s",
-        event->u.domain_shutdown.shutdown_reason,
-        get_action_on_shutdown_name(action));
-
-    if (action == LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY || action == LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_RESTART) {
-        char *corefile;
-        int rc;
-
-        xasprintf(&corefile, XEN_DUMP_DIR "/%s", d_config->c_info.name);
-        LOG("dumping core to %s", corefile);
-        rc = libxl_domain_core_dump(ctx, *r_domid, corefile, NULL);
-        if (rc) LOG("core dump failed (rc=%d).", rc);
-        free(corefile);
-        /* No point crying over spilled milk, continue on failure. */
-
-        if (action == LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY)
-            action = LIBXL_ACTION_ON_SHUTDOWN_DESTROY;
-        else
-            action = LIBXL_ACTION_ON_SHUTDOWN_RESTART;
-    }
-
-    switch (action) {
-    case LIBXL_ACTION_ON_SHUTDOWN_PRESERVE:
-        break;
-
-    case LIBXL_ACTION_ON_SHUTDOWN_RESTART_RENAME:
-        reload_domain_config(*r_domid, d_config);
-        restart = DOMAIN_RESTART_RENAME;
-        break;
-
-    case LIBXL_ACTION_ON_SHUTDOWN_RESTART:
-        reload_domain_config(*r_domid, d_config);
-        restart = DOMAIN_RESTART_NORMAL;
-        /* fall-through */
-    case LIBXL_ACTION_ON_SHUTDOWN_DESTROY:
-        LOG("Domain %d needs to be cleaned up: destroying the domain",
-            *r_domid);
-        libxl_domain_destroy(ctx, *r_domid, 0);
-        *r_domid = INVALID_DOMID;
-        break;
-
-    case LIBXL_ACTION_ON_SHUTDOWN_SOFT_RESET:
-        reload_domain_config(*r_domid, d_config);
-        restart = DOMAIN_RESTART_SOFT_RESET;
-        break;
-
-    case LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY:
-    case LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_RESTART:
-        /* Already handled these above. */
-        abort();
-    }
-
-    return restart;
-}
-
-/* Preserve a copy of a domain under a new name. Updates *r_domid */
-static int preserve_domain(uint32_t *r_domid, libxl_event *event,
-                           libxl_domain_config *d_config)
-{
-    time_t now;
-    struct tm tm;
-    char strtime[24];
-
-    libxl_uuid new_uuid;
-
-    int rc;
-
-    now = time(NULL);
-    if (now == ((time_t) -1)) {
-        LOG("Failed to get current time for domain rename");
-        return 0;
-    }
-
-    tzset();
-    if (gmtime_r(&now, &tm) == NULL) {
-        LOG("Failed to convert time to UTC");
-        return 0;
-    }
-
-    if (!strftime(&strtime[0], sizeof(strtime), "-%Y%m%dT%H%MZ", &tm)) {
-        LOG("Failed to format time as a string");
-        return 0;
-    }
-
-    libxl_uuid_generate(&new_uuid);
-
-    LOG("Preserving domain %u %s with suffix%s",
-        *r_domid, d_config->c_info.name, strtime);
-    rc = libxl_domain_preserve(ctx, *r_domid, &d_config->c_info,
-                               strtime, new_uuid);
-
-    /*
-     * Although the domain still exists it is no longer the one we are
-     * concerned with.
-     */
-    *r_domid = INVALID_DOMID;
-
-    return rc == 0 ? 1 : 0;
-}
-
-/*
- * Returns false if memory can't be freed, but also if we encounter errors.
- * Returns true in case there is already, or we manage to free it, enough
- * memory, but also if autoballoon is false.
- */
-static bool freemem(uint32_t domid, libxl_domain_build_info *b_info)
-{
-    int rc, retries = 3;
-    uint64_t need_memkb, free_memkb;
-
-    if (!autoballoon)
-        return true;
-
-    rc = libxl_domain_need_memory(ctx, b_info, &need_memkb);
-    if (rc < 0)
-        return false;
-
-    do {
-        rc = libxl_get_free_memory(ctx, &free_memkb);
-        if (rc < 0)
-            return false;
-
-        if (free_memkb >= need_memkb)
-            return true;
-
-        rc = libxl_set_memory_target(ctx, 0, free_memkb - need_memkb, 1, 0);
-        if (rc < 0)
-            return false;
-
-        /* wait until dom0 reaches its target, as long as we are making
-         * progress */
-        rc = libxl_wait_for_memory_target(ctx, 0, 10);
-        if (rc < 0)
-            return false;
-
-        retries--;
-    } while (retries > 0);
-
-    return false;
-}
-
-static void autoconnect_console(libxl_ctx *ctx_ignored,
-                                libxl_event *ev, void *priv)
-{
-    uint32_t bldomid = ev->domid;
-    int notify_fd = *(int*)priv; /* write end of the notification pipe */
-
-    libxl_event_free(ctx, ev);
-
-    console_child_report(child_console);
-
-    pid_t pid = xl_fork(child_console, "console child");
-    if (pid)
-        return;
-
-    postfork();
-
-    sleep(1);
-    libxl_primary_console_exec(ctx, bldomid, notify_fd);
-    /* Do not return. xl continued in child process */
-    perror("xl: unable to exec console client");
-    _exit(1);
-}
-
-static int domain_wait_event(uint32_t domid, libxl_event **event_r)
-{
-    int ret;
-    for (;;) {
-        ret = libxl_event_wait(ctx, event_r, LIBXL_EVENTMASK_ALL, 0,0);
-        if (ret) {
-            LOG("Domain %u, failed to get event, quitting (rc=%d)", domid, ret);
-            return ret;
-        }
-        if ((*event_r)->domid != domid) {
-            char *evstr = libxl_event_to_json(ctx, *event_r);
-            LOG("INTERNAL PROBLEM - ignoring unexpected event for"
-                " domain %d (expected %d): event=%s",
-                (*event_r)->domid, domid, evstr);
-            free(evstr);
-            libxl_event_free(ctx, *event_r);
-            continue;
-        }
-        return ret;
-    }
-}
-
-static void evdisable_disk_ejects(libxl_evgen_disk_eject **diskws,
-                                 int num_disks)
-{
-    int i;
-
-    for (i = 0; i < num_disks; i++) {
-        if (diskws[i])
-            libxl_evdisable_disk_eject(ctx, diskws[i]);
-        diskws[i] = NULL;
-    }
-}
-
-static int create_domain(struct domain_create *dom_info)
-{
-    uint32_t domid = INVALID_DOMID;
-
-    libxl_domain_config d_config;
-
-    int debug = dom_info->debug;
-    int daemonize = dom_info->daemonize;
-    int monitor = dom_info->monitor;
-    int paused = dom_info->paused;
-    int vncautopass = dom_info->vncautopass;
-    const char *config_file = dom_info->config_file;
-    const char *extra_config = dom_info->extra_config;
-    const char *restore_file = dom_info->restore_file;
-    const char *config_source = NULL;
-    const char *restore_source = NULL;
-    int migrate_fd = dom_info->migrate_fd;
-    bool config_in_json;
-
-    int i;
-    int need_daemon = daemonize;
-    int ret, rc;
-    libxl_evgen_domain_death *deathw = NULL;
-    libxl_evgen_disk_eject **diskws = NULL; /* one per disk */
-    unsigned int num_diskws = 0;
-    void *config_data = 0;
-    int config_len = 0;
-    int restore_fd = -1;
-    int restore_fd_to_close = -1;
-    int send_back_fd = -1;
-    const libxl_asyncprogress_how *autoconnect_console_how;
-    int notify_pipe[2] = { -1, -1 };
-    struct save_file_header hdr;
-    uint32_t domid_soft_reset = INVALID_DOMID;
-
-    int restoring = (restore_file || (migrate_fd >= 0));
-
-    libxl_domain_config_init(&d_config);
-
-    if (restoring) {
-        uint8_t *optdata_begin = 0;
-        const uint8_t *optdata_here = 0;
-        union { uint32_t u32; char b[4]; } u32buf;
-        uint32_t badflags;
-
-        if (migrate_fd >= 0) {
-            restore_source = "<incoming migration stream>";
-            restore_fd = migrate_fd;
-            send_back_fd = dom_info->send_back_fd;
-        } else {
-            restore_source = restore_file;
-            restore_fd = open(restore_file, O_RDONLY);
-            if (restore_fd == -1) {
-                fprintf(stderr, "Can't open restore file: %s\n", strerror(errno));
-                return ERROR_INVAL;
-            }
-            restore_fd_to_close = restore_fd;
-            rc = libxl_fd_set_cloexec(ctx, restore_fd, 1);
-            if (rc) return rc;
-        }
-
-        CHK_ERRNOVAL(libxl_read_exactly(
-                         ctx, restore_fd, &hdr, sizeof(hdr),
-                         restore_source, "header"));
-        if (memcmp(hdr.magic, savefileheader_magic, sizeof(hdr.magic))) {
-            fprintf(stderr, "File has wrong magic number -"
-                    " corrupt or for a different tool?\n");
-            return ERROR_INVAL;
-        }
-        if (hdr.byteorder != SAVEFILE_BYTEORDER_VALUE) {
-            fprintf(stderr, "File has wrong byte order\n");
-            return ERROR_INVAL;
-        }
-        fprintf(stderr, "Loading new save file %s"
-                " (new xl fmt info"
-                " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
-                restore_source, hdr.mandatory_flags, hdr.optional_flags,
-                hdr.optional_data_len);
-
-        badflags = hdr.mandatory_flags & ~XL_MANDATORY_FLAG_ALL;
-        if (badflags) {
-            fprintf(stderr, "Savefile has mandatory flag(s) 0x%"PRIx32" "
-                    "which are not supported; need newer xl\n",
-                    badflags);
-            return ERROR_INVAL;
-        }
-        if (hdr.optional_data_len) {
-            optdata_begin = xmalloc(hdr.optional_data_len);
-            CHK_ERRNOVAL(libxl_read_exactly(
-                             ctx, restore_fd, optdata_begin,
-                             hdr.optional_data_len, restore_source,
-                             "optdata"));
-        }
-
-#define OPTDATA_LEFT  (hdr.optional_data_len - (optdata_here - optdata_begin))
-#define WITH_OPTDATA(amt, body)                                 \
-            if (OPTDATA_LEFT < (amt)) {                         \
-                fprintf(stderr, "Savefile truncated.\n");       \
-                return ERROR_INVAL;                             \
-            } else {                                            \
-                body;                                           \
-                optdata_here += (amt);                          \
-            }
-
-        optdata_here = optdata_begin;
-
-        if (OPTDATA_LEFT) {
-            fprintf(stderr, " Savefile contains xl domain config%s\n",
-                    !!(hdr.mandatory_flags & XL_MANDATORY_FLAG_JSON)
-                    ? " in JSON format" : "");
-            WITH_OPTDATA(4, {
-                memcpy(u32buf.b, optdata_here, 4);
-                config_len = u32buf.u32;
-            });
-            WITH_OPTDATA(config_len, {
-                config_data = xmalloc(config_len);
-                memcpy(config_data, optdata_here, config_len);
-            });
-        }
-
-    }
-
-    if (config_file) {
-        free(config_data);  config_data = 0;
-        /* /dev/null represents special case (read config. from command line) */
-        if (!strcmp(config_file, "/dev/null")) {
-            config_len = 0;
-        } else {
-            ret = libxl_read_file_contents(ctx, config_file,
-                                           &config_data, &config_len);
-            if (ret) { fprintf(stderr, "Failed to read config file: %s: %s\n",
-                               config_file, strerror(errno)); return ERROR_FAIL; }
-        }
-        if (!restoring && extra_config && strlen(extra_config)) {
-            if (config_len > INT_MAX - (strlen(extra_config) + 2 + 1)) {
-                fprintf(stderr, "Failed to attach extra configuration\n");
-                return ERROR_FAIL;
-            }
-            /* allocate space for the extra config plus two EOLs plus \0 */
-            config_data = xrealloc(config_data, config_len
-                + strlen(extra_config) + 2 + 1);
-            config_len += sprintf(config_data + config_len, "\n%s\n",
-                extra_config);
-        }
-        config_source=config_file;
-        config_in_json = false;
-    } else {
-        if (!config_data) {
-            fprintf(stderr, "Config file not specified and"
-                    " none in save file\n");
-            return ERROR_INVAL;
-        }
-        config_source = "<saved>";
-        config_in_json = !!(hdr.mandatory_flags & XL_MANDATORY_FLAG_JSON);
-    }
-
-    if (!dom_info->quiet)
-        fprintf(stderr, "Parsing config from %s\n", config_source);
-
-    if (config_in_json) {
-        libxl_domain_config_from_json(ctx, &d_config,
-                                      (const char *)config_data);
-    } else {
-        parse_config_data(config_source, config_data, config_len, &d_config);
-    }
-
-    if (migrate_fd >= 0) {
-        if (d_config.c_info.name) {
-            /* when we receive a domain we get its name from the config
-             * file; and we receive it to a temporary name */
-            assert(!common_domname);
-
-            common_domname = d_config.c_info.name;
-            d_config.c_info.name = 0; /* steals allocation from config */
-
-            xasprintf(&d_config.c_info.name, "%s--incoming", common_domname);
-            *dom_info->migration_domname_r = strdup(d_config.c_info.name);
-        }
-    }
-
-    if (debug || dom_info->dryrun) {
-        FILE *cfg_print_fh = (debug && !dom_info->dryrun) ? stderr : stdout;
-        if (default_output_format == OUTPUT_FORMAT_SXP) {
-            printf_info_sexp(-1, &d_config, cfg_print_fh);
-        } else {
-            char *json = libxl_domain_config_to_json(ctx, &d_config);
-            if (!json) {
-                fprintf(stderr,
-                        "Failed to convert domain configuration to JSON\n");
-                exit(1);
-            }
-            fputs(json, cfg_print_fh);
-            free(json);
-            xflush_stream(cfg_print_fh);
-        }
-    }
-
-
-    ret = 0;
-    if (dom_info->dryrun)
-        goto out;
-
-start:
-    assert(domid == INVALID_DOMID);
-
-    rc = acquire_lock();
-    if (rc < 0)
-        goto error_out;
-
-    if (domid_soft_reset == INVALID_DOMID) {
-        if (!freemem(domid, &d_config.b_info)) {
-            fprintf(stderr, "failed to free memory for the domain\n");
-            ret = ERROR_FAIL;
-            goto error_out;
-        }
-    }
-
-    libxl_asyncprogress_how autoconnect_console_how_buf;
-    if ( dom_info->console_autoconnect ) {
-        if (libxl_pipe(ctx, notify_pipe)) {
-            ret = ERROR_FAIL;
-            goto error_out;
-        }
-        autoconnect_console_how_buf.callback = autoconnect_console;
-        autoconnect_console_how_buf.for_callback = &notify_pipe[1];
-        autoconnect_console_how = &autoconnect_console_how_buf;
-    }else{
-        autoconnect_console_how = 0;
-    }
-
-    if ( restoring ) {
-        libxl_domain_restore_params params;
-
-        libxl_domain_restore_params_init(&params);
-
-        params.checkpointed_stream = dom_info->checkpointed_stream;
-        params.stream_version =
-            (hdr.mandatory_flags & XL_MANDATORY_FLAG_STREAMv2) ? 2 : 1;
-        params.colo_proxy_script = dom_info->colo_proxy_script;
-
-        ret = libxl_domain_create_restore(ctx, &d_config,
-                                          &domid, restore_fd,
-                                          send_back_fd, &params,
-                                          0, autoconnect_console_how);
-
-        libxl_domain_restore_params_dispose(&params);
-
-        /*
-         * On subsequent reboot etc we should create the domain, not
-         * restore/migrate-receive it again.
-         */
-        restoring = 0;
-    } else if (domid_soft_reset != INVALID_DOMID) {
-        /* Do soft reset. */
-        ret = libxl_domain_soft_reset(ctx, &d_config, domid_soft_reset,
-                                      0, autoconnect_console_how);
-        domid = domid_soft_reset;
-        domid_soft_reset = INVALID_DOMID;
-    } else {
-        ret = libxl_domain_create_new(ctx, &d_config, &domid,
-                                      0, autoconnect_console_how);
-    }
-    if ( ret )
-        goto error_out;
-
-    release_lock();
-
-    if (restore_fd_to_close >= 0) {
-        if (close(restore_fd_to_close))
-            fprintf(stderr, "Failed to close restoring file, fd %d, errno %d\n",
-                    restore_fd_to_close, errno);
-        restore_fd_to_close = -1;
-    }
-
-    if (autoconnect_console_how) {
-        char buf[1];
-        int r;
-
-        /* Try to get notification from xenconsole. Just move on if
-         * error occurs -- it's only minor annoyance if console
-         * doesn't show up.
-         */
-        do {
-            r = read(notify_pipe[0], buf, 1);
-        } while (r == -1 && errno == EINTR);
-
-        if (r == -1)
-            fprintf(stderr,
-                    "Failed to get notification from xenconsole: %s\n",
-                    strerror(errno));
-        else if (r == 0)
-            fprintf(stderr, "Got EOF from xenconsole notification fd\n");
-        else if (r == 1 && buf[0] != 0x00)
-            fprintf(stderr, "Got unexpected response from xenconsole: %#x\n",
-                    buf[0]);
-
-        close(notify_pipe[0]);
-        close(notify_pipe[1]);
-        notify_pipe[0] = notify_pipe[1] = -1;
-    }
-
-    if (!paused)
-        libxl_domain_unpause(ctx, domid);
-
-    ret = domid; /* caller gets success in parent */
-    if (!daemonize && !monitor)
-        goto out;
-
-    if (dom_info->vnc)
-        autoconnect_vncviewer(domid, vncautopass);
-
-    if (need_daemon) {
-        char *name;
-
-        xasprintf(&name, "xl-%s", d_config.c_info.name);
-        ret = do_daemonize(name, NULL);
-        free(name);
-        if (ret) {
-            ret = (ret == 1) ? domid : ret;
-            goto out;
-        }
-        need_daemon = 0;
-    }
-    LOG("Waiting for domain %s (domid %u) to die [pid %ld]",
-        d_config.c_info.name, domid, (long)getpid());
-
-    ret = libxl_evenable_domain_death(ctx, domid, 0, &deathw);
-    if (ret) goto out;
-
-    if (!diskws) {
-        diskws = xmalloc(sizeof(*diskws) * d_config.num_disks);
-        for (i = 0; i < d_config.num_disks; i++)
-            diskws[i] = NULL;
-        num_diskws = d_config.num_disks;
-    }
-    for (i = 0; i < num_diskws; i++) {
-        if (d_config.disks[i].removable) {
-            ret = libxl_evenable_disk_eject(ctx, domid, d_config.disks[i].vdev,
-                                            0, &diskws[i]);
-            if (ret) goto out;
-        }
-    }
-    while (1) {
-        libxl_event *event;
-        ret = domain_wait_event(domid, &event);
-        if (ret) goto out;
-
-        switch (event->type) {
-
-        case LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN:
-            LOG("Domain %u has shut down, reason code %d 0x%x", domid,
-                event->u.domain_shutdown.shutdown_reason,
-                event->u.domain_shutdown.shutdown_reason);
-            switch (handle_domain_death(&domid, event, &d_config)) {
-            case DOMAIN_RESTART_SOFT_RESET:
-                domid_soft_reset = domid;
-                domid = INVALID_DOMID;
-                /* fall through */
-            case DOMAIN_RESTART_RENAME:
-                if (domid_soft_reset == INVALID_DOMID &&
-                    !preserve_domain(&domid, event, &d_config)) {
-                    libxl_event_free(ctx, event);
-                    /* If we fail then exit leaving the old domain in place. */
-                    ret = -1;
-                    goto out;
-                }
-
-                /* Otherwise fall through and restart. */
-            case DOMAIN_RESTART_NORMAL:
-                libxl_event_free(ctx, event);
-                libxl_evdisable_domain_death(ctx, deathw);
-                deathw = NULL;
-                evdisable_disk_ejects(diskws, num_diskws);
-                free(diskws);
-                diskws = NULL;
-                num_diskws = 0;
-                /* discard any other events which may have been generated */
-                while (!(ret = libxl_event_check(ctx, &event,
-                                                 LIBXL_EVENTMASK_ALL, 0,0))) {
-                    libxl_event_free(ctx, event);
-                }
-                if (ret != ERROR_NOT_READY) {
-                    LOG("warning, libxl_event_check (cleanup) failed (rc=%d)",
-                        ret);
-                }
-
-                /*
-                 * Do not attempt to reconnect if we come round again due to a
-                 * guest reboot -- the stdin/out will be disconnected by then.
-                 */
-                dom_info->console_autoconnect = 0;
-
-                /* Some settings only make sense on first boot. */
-                paused = 0;
-                if (common_domname
-                    && strcmp(d_config.c_info.name, common_domname)) {
-                    d_config.c_info.name = strdup(common_domname);
-                }
-
-                /*
-                 * XXX FIXME: If this sleep is not there then domain
-                 * re-creation fails sometimes.
-                 */
-                LOG("Done. Rebooting now");
-                sleep(2);
-                goto start;
-
-            case DOMAIN_RESTART_NONE:
-                LOG("Done. Exiting now");
-                libxl_event_free(ctx, event);
-                ret = 0;
-                goto out;
-
-            default:
-                abort();
-            }
-
-        case LIBXL_EVENT_TYPE_DOMAIN_DEATH:
-            LOG("Domain %u has been destroyed.", domid);
-            libxl_event_free(ctx, event);
-            ret = 0;
-            goto out;
-
-        case LIBXL_EVENT_TYPE_DISK_EJECT:
-            /* XXX what is this for? */
-            libxl_cdrom_insert(ctx, domid, &event->u.disk_eject.disk, NULL);
-            break;
-
-        default:;
-            char *evstr = libxl_event_to_json(ctx, event);
-            LOG("warning, got unexpected event type %d, event=%s",
-                event->type, evstr);
-            free(evstr);
-        }
-
-        libxl_event_free(ctx, event);
-    }
-
-error_out:
-    release_lock();
-    if (libxl_domid_valid_guest(domid)) {
-        libxl_domain_destroy(ctx, domid, 0);
-        domid = INVALID_DOMID;
-    }
-
-out:
-    if (restore_fd_to_close >= 0) {
-        if (close(restore_fd_to_close))
-            fprintf(stderr, "Failed to close restoring file, fd %d, errno %d\n",
-                    restore_fd_to_close, errno);
-        restore_fd_to_close = -1;
-    }
-
-    if (logfile != 2)
-        close(logfile);
-
-    libxl_domain_config_dispose(&d_config);
-
-    free(config_data);
-
-    console_child_report(child_console);
-
-    if (deathw)
-        libxl_evdisable_domain_death(ctx, deathw);
-    if (diskws) {
-        evdisable_disk_ejects(diskws, d_config.num_disks);
-        free(diskws);
-    }
-
-    /*
-     * If we have daemonized then do not return to the caller -- this has
-     * already happened in the parent.
-     */
-    if ( daemonize && !need_daemon )
-        exit(ret);
-
-    return ret;
-}
-
 void help(const char *command)
 {
     int i;
@@ -1003,127 +98,6 @@ void help(const char *command)
     }
 }
 
-static void pause_domain(uint32_t domid)
-{
-    libxl_domain_pause(ctx, domid);
-}
-
-static void unpause_domain(uint32_t domid)
-{
-    libxl_domain_unpause(ctx, domid);
-}
-
-static void destroy_domain(uint32_t domid, int force)
-{
-    int rc;
-
-    if (domid == 0 && !force) {
-        fprintf(stderr, "Not destroying domain 0; use -f to force.\n"
-                        "This can only be done when using a disaggregated "
-                        "hardware domain and toolstack.\n\n");
-        exit(EXIT_FAILURE);
-    }
-    rc = libxl_domain_destroy(ctx, domid, 0);
-    if (rc) { fprintf(stderr,"destroy failed (rc=%d)\n",rc); exit(EXIT_FAILURE); }
-}
-
-static void wait_for_domain_deaths(libxl_evgen_domain_death **deathws, int nr)
-{
-    int rc, count = 0;
-    LOG("Waiting for %d domains", nr);
-    while(1 && count < nr) {
-        libxl_event *event;
-        rc = libxl_event_wait(ctx, &event, LIBXL_EVENTMASK_ALL, 0,0);
-        if (rc) {
-            LOG("Failed to get event, quitting (rc=%d)", rc);
-            exit(EXIT_FAILURE);
-        }
-
-        switch (event->type) {
-        case LIBXL_EVENT_TYPE_DOMAIN_DEATH:
-            LOG("Domain %d has been destroyed", event->domid);
-            libxl_evdisable_domain_death(ctx, deathws[event->for_user]);
-            count++;
-            break;
-        case LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN:
-            LOG("Domain %d has been shut down, reason code %d",
-                event->domid, event->u.domain_shutdown.shutdown_reason);
-            libxl_evdisable_domain_death(ctx, deathws[event->for_user]);
-            count++;
-            break;
-        default:
-            LOG("Unexpected event type %d", event->type);
-            break;
-        }
-        libxl_event_free(ctx, event);
-    }
-}
-
-static void shutdown_domain(uint32_t domid,
-                            libxl_evgen_domain_death **deathw,
-                            libxl_ev_user for_user,
-                            int fallback_trigger)
-{
-    int rc;
-
-    fprintf(stderr, "Shutting down domain %u\n", domid);
-    rc=libxl_domain_shutdown(ctx, domid);
-    if (rc == ERROR_NOPARAVIRT) {
-        if (fallback_trigger) {
-            fprintf(stderr, "PV control interface not available:"
-                    " sending ACPI power button event.\n");
-            rc = libxl_send_trigger(ctx, domid, LIBXL_TRIGGER_POWER, 0);
-        } else {
-            fprintf(stderr, "PV control interface not available:"
-                    " external graceful shutdown not possible.\n");
-            fprintf(stderr, "Use \"-F\" to fallback to ACPI power event.\n");
-        }
-    }
-
-    if (rc) {
-        fprintf(stderr,"shutdown failed (rc=%d)\n",rc);exit(EXIT_FAILURE);
-    }
-
-    if (deathw) {
-        rc = libxl_evenable_domain_death(ctx, domid, for_user, deathw);
-        if (rc) {
-            fprintf(stderr,"wait for death failed (evgen, rc=%d)\n",rc);
-            exit(EXIT_FAILURE);
-        }
-    }
-}
-
-static void reboot_domain(uint32_t domid, libxl_evgen_domain_death **deathw,
-                          libxl_ev_user for_user, int fallback_trigger)
-{
-    int rc;
-
-    fprintf(stderr, "Rebooting domain %u\n", domid);
-    rc=libxl_domain_reboot(ctx, domid);
-    if (rc == ERROR_NOPARAVIRT) {
-        if (fallback_trigger) {
-            fprintf(stderr, "PV control interface not available:"
-                    " sending ACPI reset button event.\n");
-            rc = libxl_send_trigger(ctx, domid, LIBXL_TRIGGER_RESET, 0);
-        } else {
-            fprintf(stderr, "PV control interface not available:"
-                    " external graceful reboot not possible.\n");
-            fprintf(stderr, "Use \"-F\" to fallback to ACPI reset event.\n");
-        }
-    }
-    if (rc) {
-        fprintf(stderr,"reboot failed (rc=%d)\n",rc);exit(EXIT_FAILURE);
-    }
-
-    if (deathw) {
-        rc = libxl_evenable_domain_death(ctx, domid, for_user, deathw);
-        if (rc) {
-            fprintf(stderr,"wait for death failed (evgen, rc=%d)\n",rc);
-            exit(EXIT_FAILURE);
-        }
-    }
-}
-
 #ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
 static void save_domain_core_begin(uint32_t domid,
                                    const char *override_config_file,
@@ -1915,223 +889,6 @@ int main_migrate(int argc, char **argv)
 }
 #endif
 
-int main_pause(int argc, char **argv)
-{
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "pause", 1) {
-        /* No options */
-    }
-
-    pause_domain(xfind_domain(argv[optind]));
-
-    return EXIT_SUCCESS;
-}
-
-int main_unpause(int argc, char **argv)
-{
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "unpause", 1) {
-        /* No options */
-    }
-
-    unpause_domain(xfind_domain(argv[optind]));
-
-    return EXIT_SUCCESS;
-}
-
-int main_destroy(int argc, char **argv)
-{
-    int opt;
-    int force = 0;
-
-    SWITCH_FOREACH_OPT(opt, "f", NULL, "destroy", 1) {
-    case 'f':
-        force = 1;
-        break;
-    }
-
-    destroy_domain(xfind_domain(argv[optind]), force);
-    return EXIT_SUCCESS;
-}
-
-static int main_shutdown_or_reboot(int do_reboot, int argc, char **argv)
-{
-    const char *what = do_reboot ? "reboot" : "shutdown";
-    void (*fn)(uint32_t domid,
-               libxl_evgen_domain_death **, libxl_ev_user, int) =
-        do_reboot ? &reboot_domain : &shutdown_domain;
-    int opt, i, nb_domain;
-    int wait_for_it = 0, all = 0, nrdeathws = 0;
-    int fallback_trigger = 0;
-    static struct option opts[] = {
-        {"all", 0, 0, 'a'},
-        {"wait", 0, 0, 'w'},
-        COMMON_LONG_OPTS
-    };
-
-    SWITCH_FOREACH_OPT(opt, "awF", opts, what, 0) {
-    case 'a':
-        all = 1;
-        break;
-    case 'w':
-        wait_for_it = 1;
-        break;
-    case 'F':
-        fallback_trigger = 1;
-        break;
-    }
-
-    if (!argv[optind] && !all) {
-        fprintf(stderr, "You must specify -a or a domain id.\n\n");
-        return EXIT_FAILURE;
-    }
-
-    if (all) {
-        libxl_dominfo *dominfo;
-        libxl_evgen_domain_death **deathws = NULL;
-        if (!(dominfo = libxl_list_domain(ctx, &nb_domain))) {
-            fprintf(stderr, "libxl_list_domain failed.\n");
-            return EXIT_FAILURE;
-        }
-
-        if (wait_for_it)
-            deathws = calloc(nb_domain, sizeof(*deathws));
-
-        for (i = 0; i<nb_domain; i++) {
-            if (dominfo[i].domid == 0 || dominfo[i].never_stop)
-                continue;
-            fn(dominfo[i].domid, deathws ? &deathws[i] : NULL, i,
-               fallback_trigger);
-            nrdeathws++;
-        }
-
-        if (deathws) {
-            wait_for_domain_deaths(deathws, nrdeathws);
-            free(deathws);
-        }
-
-        libxl_dominfo_list_free(dominfo, nb_domain);
-    } else {
-        libxl_evgen_domain_death *deathw = NULL;
-        uint32_t domid = xfind_domain(argv[optind]);
-
-        fn(domid, wait_for_it ? &deathw : NULL, 0, fallback_trigger);
-
-        if (wait_for_it)
-            wait_for_domain_deaths(&deathw, 1);
-    }
-
-
-    return EXIT_SUCCESS;
-}
-
-int main_shutdown(int argc, char **argv)
-{
-    return main_shutdown_or_reboot(0, argc, argv);
-}
-
-int main_reboot(int argc, char **argv)
-{
-    return main_shutdown_or_reboot(1, argc, argv);
-}
-
-int main_create(int argc, char **argv)
-{
-    const char *filename = NULL;
-    struct domain_create dom_info;
-    int paused = 0, debug = 0, daemonize = 1, console_autoconnect = 0,
-        quiet = 0, monitor = 1, vnc = 0, vncautopass = 0;
-    int opt, rc;
-    static struct option opts[] = {
-        {"dryrun", 0, 0, 'n'},
-        {"quiet", 0, 0, 'q'},
-        {"defconfig", 1, 0, 'f'},
-        {"vncviewer", 0, 0, 'V'},
-        {"vncviewer-autopass", 0, 0, 'A'},
-        COMMON_LONG_OPTS
-    };
-
-    dom_info.extra_config = NULL;
-
-    if (argv[1] && argv[1][0] != '-' && !strchr(argv[1], '=')) {
-        filename = argv[1];
-        argc--; argv++;
-    }
-
-    SWITCH_FOREACH_OPT(opt, "Fnqf:pcdeVA", opts, "create", 0) {
-    case 'f':
-        filename = optarg;
-        break;
-    case 'p':
-        paused = 1;
-        break;
-    case 'c':
-        console_autoconnect = 1;
-        break;
-    case 'd':
-        debug = 1;
-        break;
-    case 'F':
-        daemonize = 0;
-        break;
-    case 'e':
-        daemonize = 0;
-        monitor = 0;
-        break;
-    case 'n':
-        dryrun_only = 1;
-        break;
-    case 'q':
-        quiet = 1;
-        break;
-    case 'V':
-        vnc = 1;
-        break;
-    case 'A':
-        vnc = vncautopass = 1;
-        break;
-    }
-
-    memset(&dom_info, 0, sizeof(dom_info));
-
-    for (; optind < argc; optind++) {
-        if (strchr(argv[optind], '=') != NULL) {
-            xstring_realloc_append(&dom_info.extra_config, argv[optind]);
-            xstring_realloc_append(&dom_info.extra_config, "\n");
-        } else if (!filename) {
-            filename = argv[optind];
-        } else {
-            help("create");
-            free(dom_info.extra_config);
-            return 2;
-        }
-    }
-
-    dom_info.debug = debug;
-    dom_info.daemonize = daemonize;
-    dom_info.monitor = monitor;
-    dom_info.paused = paused;
-    dom_info.dryrun = dryrun_only;
-    dom_info.quiet = quiet;
-    dom_info.config_file = filename;
-    dom_info.migrate_fd = -1;
-    dom_info.send_back_fd = -1;
-    dom_info.vnc = vnc;
-    dom_info.vncautopass = vncautopass;
-    dom_info.console_autoconnect = console_autoconnect;
-
-    rc = create_domain(&dom_info);
-    if (rc < 0) {
-        free(dom_info.extra_config);
-        return -rc;
-    }
-
-    free(dom_info.extra_config);
-    return 0;
-}
-
 #ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
 int main_remus(int argc, char **argv)
 {
diff --git a/tools/xl/xl_vmcontrol.c b/tools/xl/xl_vmcontrol.c
new file mode 100644
index 0000000000..309c2fb113
--- /dev/null
+++ b/tools/xl/xl_vmcontrol.c
@@ -0,0 +1,1225 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+extern libxl_ctx *ctx;
+extern int logfile;
+extern const char *common_domname;
+
+static int fd_lock = -1;
+
+static void pause_domain(uint32_t domid)
+{
+    libxl_domain_pause(ctx, domid);
+}
+
+static void unpause_domain(uint32_t domid)
+{
+    libxl_domain_unpause(ctx, domid);
+}
+
+static void destroy_domain(uint32_t domid, int force)
+{
+    int rc;
+
+    if (domid == 0 && !force) {
+        fprintf(stderr, "Not destroying domain 0; use -f to force.\n"
+                        "This can only be done when using a disaggregated "
+                        "hardware domain and toolstack.\n\n");
+        exit(EXIT_FAILURE);
+    }
+    rc = libxl_domain_destroy(ctx, domid, 0);
+    if (rc) { fprintf(stderr,"destroy failed (rc=%d)\n",rc); exit(EXIT_FAILURE); }
+}
+
+int main_pause(int argc, char **argv)
+{
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "pause", 1) {
+        /* No options */
+    }
+
+    pause_domain(xfind_domain(argv[optind]));
+
+    return EXIT_SUCCESS;
+}
+
+int main_unpause(int argc, char **argv)
+{
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "unpause", 1) {
+        /* No options */
+    }
+
+    unpause_domain(xfind_domain(argv[optind]));
+
+    return EXIT_SUCCESS;
+}
+
+int main_destroy(int argc, char **argv)
+{
+    int opt;
+    int force = 0;
+
+    SWITCH_FOREACH_OPT(opt, "f", NULL, "destroy", 1) {
+    case 'f':
+        force = 1;
+        break;
+    }
+
+    destroy_domain(xfind_domain(argv[optind]), force);
+    return EXIT_SUCCESS;
+}
+
+static void reboot_domain(uint32_t domid, libxl_evgen_domain_death **deathw,
+                          libxl_ev_user for_user, int fallback_trigger)
+{
+    int rc;
+
+    fprintf(stderr, "Rebooting domain %u\n", domid);
+    rc=libxl_domain_reboot(ctx, domid);
+    if (rc == ERROR_NOPARAVIRT) {
+        if (fallback_trigger) {
+            fprintf(stderr, "PV control interface not available:"
+                    " sending ACPI reset button event.\n");
+            rc = libxl_send_trigger(ctx, domid, LIBXL_TRIGGER_RESET, 0);
+        } else {
+            fprintf(stderr, "PV control interface not available:"
+                    " external graceful reboot not possible.\n");
+            fprintf(stderr, "Use \"-F\" to fallback to ACPI reset event.\n");
+        }
+    }
+    if (rc) {
+        fprintf(stderr,"reboot failed (rc=%d)\n",rc);exit(EXIT_FAILURE);
+    }
+
+    if (deathw) {
+        rc = libxl_evenable_domain_death(ctx, domid, for_user, deathw);
+        if (rc) {
+            fprintf(stderr,"wait for death failed (evgen, rc=%d)\n",rc);
+            exit(EXIT_FAILURE);
+        }
+    }
+}
+
+static void shutdown_domain(uint32_t domid,
+                            libxl_evgen_domain_death **deathw,
+                            libxl_ev_user for_user,
+                            int fallback_trigger)
+{
+    int rc;
+
+    fprintf(stderr, "Shutting down domain %u\n", domid);
+    rc=libxl_domain_shutdown(ctx, domid);
+    if (rc == ERROR_NOPARAVIRT) {
+        if (fallback_trigger) {
+            fprintf(stderr, "PV control interface not available:"
+                    " sending ACPI power button event.\n");
+            rc = libxl_send_trigger(ctx, domid, LIBXL_TRIGGER_POWER, 0);
+        } else {
+            fprintf(stderr, "PV control interface not available:"
+                    " external graceful shutdown not possible.\n");
+            fprintf(stderr, "Use \"-F\" to fallback to ACPI power event.\n");
+        }
+    }
+
+    if (rc) {
+        fprintf(stderr,"shutdown failed (rc=%d)\n",rc);exit(EXIT_FAILURE);
+    }
+
+    if (deathw) {
+        rc = libxl_evenable_domain_death(ctx, domid, for_user, deathw);
+        if (rc) {
+            fprintf(stderr,"wait for death failed (evgen, rc=%d)\n",rc);
+            exit(EXIT_FAILURE);
+        }
+    }
+}
+
+static void wait_for_domain_deaths(libxl_evgen_domain_death **deathws, int nr)
+{
+    int rc, count = 0;
+    LOG("Waiting for %d domains", nr);
+    while(1 && count < nr) {
+        libxl_event *event;
+        rc = libxl_event_wait(ctx, &event, LIBXL_EVENTMASK_ALL, 0,0);
+        if (rc) {
+            LOG("Failed to get event, quitting (rc=%d)", rc);
+            exit(EXIT_FAILURE);
+        }
+
+        switch (event->type) {
+        case LIBXL_EVENT_TYPE_DOMAIN_DEATH:
+            LOG("Domain %d has been destroyed", event->domid);
+            libxl_evdisable_domain_death(ctx, deathws[event->for_user]);
+            count++;
+            break;
+        case LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN:
+            LOG("Domain %d has been shut down, reason code %d",
+                event->domid, event->u.domain_shutdown.shutdown_reason);
+            libxl_evdisable_domain_death(ctx, deathws[event->for_user]);
+            count++;
+            break;
+        default:
+            LOG("Unexpected event type %d", event->type);
+            break;
+        }
+        libxl_event_free(ctx, event);
+    }
+}
+
+static int main_shutdown_or_reboot(int do_reboot, int argc, char **argv)
+{
+    const char *what = do_reboot ? "reboot" : "shutdown";
+    void (*fn)(uint32_t domid,
+               libxl_evgen_domain_death **, libxl_ev_user, int) =
+        do_reboot ? &reboot_domain : &shutdown_domain;
+    int opt, i, nb_domain;
+    int wait_for_it = 0, all = 0, nrdeathws = 0;
+    int fallback_trigger = 0;
+    static struct option opts[] = {
+        {"all", 0, 0, 'a'},
+        {"wait", 0, 0, 'w'},
+        COMMON_LONG_OPTS
+    };
+
+    SWITCH_FOREACH_OPT(opt, "awF", opts, what, 0) {
+    case 'a':
+        all = 1;
+        break;
+    case 'w':
+        wait_for_it = 1;
+        break;
+    case 'F':
+        fallback_trigger = 1;
+        break;
+    }
+
+    if (!argv[optind] && !all) {
+        fprintf(stderr, "You must specify -a or a domain id.\n\n");
+        return EXIT_FAILURE;
+    }
+
+    if (all) {
+        libxl_dominfo *dominfo;
+        libxl_evgen_domain_death **deathws = NULL;
+        if (!(dominfo = libxl_list_domain(ctx, &nb_domain))) {
+            fprintf(stderr, "libxl_list_domain failed.\n");
+            return EXIT_FAILURE;
+        }
+
+        if (wait_for_it)
+            deathws = calloc(nb_domain, sizeof(*deathws));
+
+        for (i = 0; i<nb_domain; i++) {
+            if (dominfo[i].domid == 0 || dominfo[i].never_stop)
+                continue;
+            fn(dominfo[i].domid, deathws ? &deathws[i] : NULL, i,
+               fallback_trigger);
+            nrdeathws++;
+        }
+
+        if (deathws) {
+            wait_for_domain_deaths(deathws, nrdeathws);
+            free(deathws);
+        }
+
+        libxl_dominfo_list_free(dominfo, nb_domain);
+    } else {
+        libxl_evgen_domain_death *deathw = NULL;
+        uint32_t domid = xfind_domain(argv[optind]);
+
+        fn(domid, wait_for_it ? &deathw : NULL, 0, fallback_trigger);
+
+        if (wait_for_it)
+            wait_for_domain_deaths(&deathw, 1);
+    }
+
+
+    return EXIT_SUCCESS;
+}
+
+int main_shutdown(int argc, char **argv)
+{
+    return main_shutdown_or_reboot(0, argc, argv);
+}
+
+int main_reboot(int argc, char **argv)
+{
+    return main_shutdown_or_reboot(1, argc, argv);
+}
+
+static void evdisable_disk_ejects(libxl_evgen_disk_eject **diskws,
+                                 int num_disks)
+{
+    int i;
+
+    for (i = 0; i < num_disks; i++) {
+        if (diskws[i])
+            libxl_evdisable_disk_eject(ctx, diskws[i]);
+        diskws[i] = NULL;
+    }
+}
+
+static int domain_wait_event(uint32_t domid, libxl_event **event_r)
+{
+    int ret;
+    for (;;) {
+        ret = libxl_event_wait(ctx, event_r, LIBXL_EVENTMASK_ALL, 0,0);
+        if (ret) {
+            LOG("Domain %u, failed to get event, quitting (rc=%d)", domid, ret);
+            return ret;
+        }
+        if ((*event_r)->domid != domid) {
+            char *evstr = libxl_event_to_json(ctx, *event_r);
+            LOG("INTERNAL PROBLEM - ignoring unexpected event for"
+                " domain %d (expected %d): event=%s",
+                (*event_r)->domid, domid, evstr);
+            free(evstr);
+            libxl_event_free(ctx, *event_r);
+            continue;
+        }
+        return ret;
+    }
+}
+
+/*
+ * Returns false if memory can't be freed, but also if we encounter errors.
+ * Returns true in case there is already, or we manage to free it, enough
+ * memory, but also if autoballoon is false.
+ */
+static bool freemem(uint32_t domid, libxl_domain_build_info *b_info)
+{
+    int rc, retries = 3;
+    uint64_t need_memkb, free_memkb;
+
+    if (!autoballoon)
+        return true;
+
+    rc = libxl_domain_need_memory(ctx, b_info, &need_memkb);
+    if (rc < 0)
+        return false;
+
+    do {
+        rc = libxl_get_free_memory(ctx, &free_memkb);
+        if (rc < 0)
+            return false;
+
+        if (free_memkb >= need_memkb)
+            return true;
+
+        rc = libxl_set_memory_target(ctx, 0, free_memkb - need_memkb, 1, 0);
+        if (rc < 0)
+            return false;
+
+        /* wait until dom0 reaches its target, as long as we are making
+         * progress */
+        rc = libxl_wait_for_memory_target(ctx, 0, 10);
+        if (rc < 0)
+            return false;
+
+        retries--;
+    } while (retries > 0);
+
+    return false;
+}
+
+static void reload_domain_config(uint32_t domid,
+                                 libxl_domain_config *d_config)
+{
+    int rc;
+    uint8_t *t_data;
+    int ret, t_len;
+    libxl_domain_config d_config_new;
+
+    /* In case user has used "config-update" to store a new config
+     * file.
+     */
+    ret = libxl_userdata_retrieve(ctx, domid, "xl", &t_data, &t_len);
+    if (ret && errno != ENOENT) {
+        LOG("\"xl\" configuration found but failed to load\n");
+    }
+    if (t_len > 0) {
+        LOG("\"xl\" configuration found, using it\n");
+        libxl_domain_config_dispose(d_config);
+        libxl_domain_config_init(d_config);
+        parse_config_data("<updated>", (const char *)t_data,
+                          t_len, d_config);
+        free(t_data);
+        libxl_userdata_unlink(ctx, domid, "xl");
+        return;
+    }
+
+    libxl_domain_config_init(&d_config_new);
+    rc = libxl_retrieve_domain_configuration(ctx, domid, &d_config_new);
+    if (rc) {
+        LOG("failed to retrieve guest configuration (rc=%d). "
+            "reusing old configuration", rc);
+        libxl_domain_config_dispose(&d_config_new);
+    } else {
+        libxl_domain_config_dispose(d_config);
+        /* Steal allocations */
+        memcpy(d_config, &d_config_new, sizeof(libxl_domain_config));
+    }
+}
+
+/* Can update r_domid if domain is destroyed */
+static domain_restart_type handle_domain_death(uint32_t *r_domid,
+                                               libxl_event *event,
+                                               libxl_domain_config *d_config)
+{
+    domain_restart_type restart = DOMAIN_RESTART_NONE;
+    libxl_action_on_shutdown action;
+
+    switch (event->u.domain_shutdown.shutdown_reason) {
+    case LIBXL_SHUTDOWN_REASON_POWEROFF:
+        action = d_config->on_poweroff;
+        break;
+    case LIBXL_SHUTDOWN_REASON_REBOOT:
+        action = d_config->on_reboot;
+        break;
+    case LIBXL_SHUTDOWN_REASON_SUSPEND:
+        LOG("Domain has suspended.");
+        return 0;
+    case LIBXL_SHUTDOWN_REASON_CRASH:
+        action = d_config->on_crash;
+        break;
+    case LIBXL_SHUTDOWN_REASON_WATCHDOG:
+        action = d_config->on_watchdog;
+        break;
+    case LIBXL_SHUTDOWN_REASON_SOFT_RESET:
+        action = d_config->on_soft_reset;
+        break;
+    default:
+        LOG("Unknown shutdown reason code %d. Destroying domain.",
+            event->u.domain_shutdown.shutdown_reason);
+        action = LIBXL_ACTION_ON_SHUTDOWN_DESTROY;
+    }
+
+    LOG("Action for shutdown reason code %d is %s",
+        event->u.domain_shutdown.shutdown_reason,
+        get_action_on_shutdown_name(action));
+
+    if (action == LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY || action == LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_RESTART) {
+        char *corefile;
+        int rc;
+
+        xasprintf(&corefile, XEN_DUMP_DIR "/%s", d_config->c_info.name);
+        LOG("dumping core to %s", corefile);
+        rc = libxl_domain_core_dump(ctx, *r_domid, corefile, NULL);
+        if (rc) LOG("core dump failed (rc=%d).", rc);
+        free(corefile);
+        /* No point crying over spilled milk, continue on failure. */
+
+        if (action == LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY)
+            action = LIBXL_ACTION_ON_SHUTDOWN_DESTROY;
+        else
+            action = LIBXL_ACTION_ON_SHUTDOWN_RESTART;
+    }
+
+    switch (action) {
+    case LIBXL_ACTION_ON_SHUTDOWN_PRESERVE:
+        break;
+
+    case LIBXL_ACTION_ON_SHUTDOWN_RESTART_RENAME:
+        reload_domain_config(*r_domid, d_config);
+        restart = DOMAIN_RESTART_RENAME;
+        break;
+
+    case LIBXL_ACTION_ON_SHUTDOWN_RESTART:
+        reload_domain_config(*r_domid, d_config);
+        restart = DOMAIN_RESTART_NORMAL;
+        /* fall-through */
+    case LIBXL_ACTION_ON_SHUTDOWN_DESTROY:
+        LOG("Domain %d needs to be cleaned up: destroying the domain",
+            *r_domid);
+        libxl_domain_destroy(ctx, *r_domid, 0);
+        *r_domid = INVALID_DOMID;
+        break;
+
+    case LIBXL_ACTION_ON_SHUTDOWN_SOFT_RESET:
+        reload_domain_config(*r_domid, d_config);
+        restart = DOMAIN_RESTART_SOFT_RESET;
+        break;
+
+    case LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY:
+    case LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_RESTART:
+        /* Already handled these above. */
+        abort();
+    }
+
+    return restart;
+}
+
+/* Preserve a copy of a domain under a new name. Updates *r_domid */
+static int preserve_domain(uint32_t *r_domid, libxl_event *event,
+                           libxl_domain_config *d_config)
+{
+    time_t now;
+    struct tm tm;
+    char strtime[24];
+
+    libxl_uuid new_uuid;
+
+    int rc;
+
+    now = time(NULL);
+    if (now == ((time_t) -1)) {
+        LOG("Failed to get current time for domain rename");
+        return 0;
+    }
+
+    tzset();
+    if (gmtime_r(&now, &tm) == NULL) {
+        LOG("Failed to convert time to UTC");
+        return 0;
+    }
+
+    if (!strftime(&strtime[0], sizeof(strtime), "-%Y%m%dT%H%MZ", &tm)) {
+        LOG("Failed to format time as a string");
+        return 0;
+    }
+
+    libxl_uuid_generate(&new_uuid);
+
+    LOG("Preserving domain %u %s with suffix%s",
+        *r_domid, d_config->c_info.name, strtime);
+    rc = libxl_domain_preserve(ctx, *r_domid, &d_config->c_info,
+                               strtime, new_uuid);
+
+    /*
+     * Although the domain still exists it is no longer the one we are
+     * concerned with.
+     */
+    *r_domid = INVALID_DOMID;
+
+    return rc == 0 ? 1 : 0;
+}
+
+static void console_child_report(xlchildnum child)
+{
+    if (xl_child_pid(child))
+        child_report(child);
+}
+
+static int vncviewer(uint32_t domid, int autopass)
+{
+    libxl_vncviewer_exec(ctx, domid, autopass);
+    fprintf(stderr, "Unable to execute vncviewer\n");
+    return 1;
+}
+
+static void autoconnect_vncviewer(uint32_t domid, int autopass)
+{
+   console_child_report(child_vncviewer);
+
+    pid_t pid = xl_fork(child_vncviewer, "vncviewer child");
+    if (pid)
+        return;
+
+    postfork();
+
+    sleep(1);
+    vncviewer(domid, autopass);
+    _exit(EXIT_FAILURE);
+}
+
+static int acquire_lock(void)
+{
+    int rc;
+    struct flock fl;
+
+    /* lock already acquired */
+    if (fd_lock >= 0)
+        return ERROR_INVAL;
+
+    fl.l_type = F_WRLCK;
+    fl.l_whence = SEEK_SET;
+    fl.l_start = 0;
+    fl.l_len = 0;
+    fd_lock = open(lockfile, O_WRONLY|O_CREAT, S_IWUSR);
+    if (fd_lock < 0) {
+        fprintf(stderr, "cannot open the lockfile %s errno=%d\n", lockfile, errno);
+        return ERROR_FAIL;
+    }
+    if (fcntl(fd_lock, F_SETFD, FD_CLOEXEC) < 0) {
+        close(fd_lock);
+        fprintf(stderr, "cannot set cloexec to lockfile %s errno=%d\n", lockfile, errno);
+        return ERROR_FAIL;
+    }
+get_lock:
+    rc = fcntl(fd_lock, F_SETLKW, &fl);
+    if (rc < 0 && errno == EINTR)
+        goto get_lock;
+    if (rc < 0) {
+        fprintf(stderr, "cannot acquire lock %s errno=%d\n", lockfile, errno);
+        rc = ERROR_FAIL;
+    } else
+        rc = 0;
+    return rc;
+}
+
+static int release_lock(void)
+{
+    int rc;
+    struct flock fl;
+
+    /* lock not acquired */
+    if (fd_lock < 0)
+        return ERROR_INVAL;
+
+release_lock:
+    fl.l_type = F_UNLCK;
+    fl.l_whence = SEEK_SET;
+    fl.l_start = 0;
+    fl.l_len = 0;
+
+    rc = fcntl(fd_lock, F_SETLKW, &fl);
+    if (rc < 0 && errno == EINTR)
+        goto release_lock;
+    if (rc < 0) {
+        fprintf(stderr, "cannot release lock %s, errno=%d\n", lockfile, errno);
+        rc = ERROR_FAIL;
+    } else
+        rc = 0;
+    close(fd_lock);
+    fd_lock = -1;
+
+    return rc;
+}
+
+
+static void autoconnect_console(libxl_ctx *ctx_ignored,
+                                libxl_event *ev, void *priv)
+{
+    uint32_t bldomid = ev->domid;
+    int notify_fd = *(int*)priv; /* write end of the notification pipe */
+
+    libxl_event_free(ctx, ev);
+
+    console_child_report(child_console);
+
+    pid_t pid = xl_fork(child_console, "console child");
+    if (pid)
+        return;
+
+    postfork();
+
+    sleep(1);
+    libxl_primary_console_exec(ctx, bldomid, notify_fd);
+    /* Do not return. xl continued in child process */
+    perror("xl: unable to exec console client");
+    _exit(1);
+}
+
+int create_domain(struct domain_create *dom_info)
+{
+    uint32_t domid = INVALID_DOMID;
+
+    libxl_domain_config d_config;
+
+    int debug = dom_info->debug;
+    int daemonize = dom_info->daemonize;
+    int monitor = dom_info->monitor;
+    int paused = dom_info->paused;
+    int vncautopass = dom_info->vncautopass;
+    const char *config_file = dom_info->config_file;
+    const char *extra_config = dom_info->extra_config;
+    const char *restore_file = dom_info->restore_file;
+    const char *config_source = NULL;
+    const char *restore_source = NULL;
+    int migrate_fd = dom_info->migrate_fd;
+    bool config_in_json;
+
+    int i;
+    int need_daemon = daemonize;
+    int ret, rc;
+    libxl_evgen_domain_death *deathw = NULL;
+    libxl_evgen_disk_eject **diskws = NULL; /* one per disk */
+    unsigned int num_diskws = 0;
+    void *config_data = 0;
+    int config_len = 0;
+    int restore_fd = -1;
+    int restore_fd_to_close = -1;
+    int send_back_fd = -1;
+    const libxl_asyncprogress_how *autoconnect_console_how;
+    int notify_pipe[2] = { -1, -1 };
+    struct save_file_header hdr;
+    uint32_t domid_soft_reset = INVALID_DOMID;
+
+    int restoring = (restore_file || (migrate_fd >= 0));
+
+    libxl_domain_config_init(&d_config);
+
+    if (restoring) {
+        uint8_t *optdata_begin = 0;
+        const uint8_t *optdata_here = 0;
+        union { uint32_t u32; char b[4]; } u32buf;
+        uint32_t badflags;
+
+        if (migrate_fd >= 0) {
+            restore_source = "<incoming migration stream>";
+            restore_fd = migrate_fd;
+            send_back_fd = dom_info->send_back_fd;
+        } else {
+            restore_source = restore_file;
+            restore_fd = open(restore_file, O_RDONLY);
+            if (restore_fd == -1) {
+                fprintf(stderr, "Can't open restore file: %s\n", strerror(errno));
+                return ERROR_INVAL;
+            }
+            restore_fd_to_close = restore_fd;
+            rc = libxl_fd_set_cloexec(ctx, restore_fd, 1);
+            if (rc) return rc;
+        }
+
+        CHK_ERRNOVAL(libxl_read_exactly(
+                         ctx, restore_fd, &hdr, sizeof(hdr),
+                         restore_source, "header"));
+        if (memcmp(hdr.magic, savefileheader_magic, sizeof(hdr.magic))) {
+            fprintf(stderr, "File has wrong magic number -"
+                    " corrupt or for a different tool?\n");
+            return ERROR_INVAL;
+        }
+        if (hdr.byteorder != SAVEFILE_BYTEORDER_VALUE) {
+            fprintf(stderr, "File has wrong byte order\n");
+            return ERROR_INVAL;
+        }
+        fprintf(stderr, "Loading new save file %s"
+                " (new xl fmt info"
+                " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
+                restore_source, hdr.mandatory_flags, hdr.optional_flags,
+                hdr.optional_data_len);
+
+        badflags = hdr.mandatory_flags & ~XL_MANDATORY_FLAG_ALL;
+        if (badflags) {
+            fprintf(stderr, "Savefile has mandatory flag(s) 0x%"PRIx32" "
+                    "which are not supported; need newer xl\n",
+                    badflags);
+            return ERROR_INVAL;
+        }
+        if (hdr.optional_data_len) {
+            optdata_begin = xmalloc(hdr.optional_data_len);
+            CHK_ERRNOVAL(libxl_read_exactly(
+                             ctx, restore_fd, optdata_begin,
+                             hdr.optional_data_len, restore_source,
+                             "optdata"));
+        }
+
+#define OPTDATA_LEFT  (hdr.optional_data_len - (optdata_here - optdata_begin))
+#define WITH_OPTDATA(amt, body)                                 \
+            if (OPTDATA_LEFT < (amt)) {                         \
+                fprintf(stderr, "Savefile truncated.\n");       \
+                return ERROR_INVAL;                             \
+            } else {                                            \
+                body;                                           \
+                optdata_here += (amt);                          \
+            }
+
+        optdata_here = optdata_begin;
+
+        if (OPTDATA_LEFT) {
+            fprintf(stderr, " Savefile contains xl domain config%s\n",
+                    !!(hdr.mandatory_flags & XL_MANDATORY_FLAG_JSON)
+                    ? " in JSON format" : "");
+            WITH_OPTDATA(4, {
+                memcpy(u32buf.b, optdata_here, 4);
+                config_len = u32buf.u32;
+            });
+            WITH_OPTDATA(config_len, {
+                config_data = xmalloc(config_len);
+                memcpy(config_data, optdata_here, config_len);
+            });
+        }
+
+    }
+
+    if (config_file) {
+        free(config_data);  config_data = 0;
+        /* /dev/null represents special case (read config. from command line) */
+        if (!strcmp(config_file, "/dev/null")) {
+            config_len = 0;
+        } else {
+            ret = libxl_read_file_contents(ctx, config_file,
+                                           &config_data, &config_len);
+            if (ret) { fprintf(stderr, "Failed to read config file: %s: %s\n",
+                               config_file, strerror(errno)); return ERROR_FAIL; }
+        }
+        if (!restoring && extra_config && strlen(extra_config)) {
+            if (config_len > INT_MAX - (strlen(extra_config) + 2 + 1)) {
+                fprintf(stderr, "Failed to attach extra configuration\n");
+                return ERROR_FAIL;
+            }
+            /* allocate space for the extra config plus two EOLs plus \0 */
+            config_data = xrealloc(config_data, config_len
+                + strlen(extra_config) + 2 + 1);
+            config_len += sprintf(config_data + config_len, "\n%s\n",
+                extra_config);
+        }
+        config_source=config_file;
+        config_in_json = false;
+    } else {
+        if (!config_data) {
+            fprintf(stderr, "Config file not specified and"
+                    " none in save file\n");
+            return ERROR_INVAL;
+        }
+        config_source = "<saved>";
+        config_in_json = !!(hdr.mandatory_flags & XL_MANDATORY_FLAG_JSON);
+    }
+
+    if (!dom_info->quiet)
+        fprintf(stderr, "Parsing config from %s\n", config_source);
+
+    if (config_in_json) {
+        libxl_domain_config_from_json(ctx, &d_config,
+                                      (const char *)config_data);
+    } else {
+        parse_config_data(config_source, config_data, config_len, &d_config);
+    }
+
+    if (migrate_fd >= 0) {
+        if (d_config.c_info.name) {
+            /* when we receive a domain we get its name from the config
+             * file; and we receive it to a temporary name */
+            assert(!common_domname);
+
+            common_domname = d_config.c_info.name;
+            d_config.c_info.name = 0; /* steals allocation from config */
+
+            xasprintf(&d_config.c_info.name, "%s--incoming", common_domname);
+            *dom_info->migration_domname_r = strdup(d_config.c_info.name);
+        }
+    }
+
+    if (debug || dom_info->dryrun) {
+        FILE *cfg_print_fh = (debug && !dom_info->dryrun) ? stderr : stdout;
+        if (default_output_format == OUTPUT_FORMAT_SXP) {
+            printf_info_sexp(-1, &d_config, cfg_print_fh);
+        } else {
+            char *json = libxl_domain_config_to_json(ctx, &d_config);
+            if (!json) {
+                fprintf(stderr,
+                        "Failed to convert domain configuration to JSON\n");
+                exit(1);
+            }
+            fputs(json, cfg_print_fh);
+            free(json);
+            xflush_stream(cfg_print_fh);
+        }
+    }
+
+
+    ret = 0;
+    if (dom_info->dryrun)
+        goto out;
+
+start:
+    assert(domid == INVALID_DOMID);
+
+    rc = acquire_lock();
+    if (rc < 0)
+        goto error_out;
+
+    if (domid_soft_reset == INVALID_DOMID) {
+        if (!freemem(domid, &d_config.b_info)) {
+            fprintf(stderr, "failed to free memory for the domain\n");
+            ret = ERROR_FAIL;
+            goto error_out;
+        }
+    }
+
+    libxl_asyncprogress_how autoconnect_console_how_buf;
+    if ( dom_info->console_autoconnect ) {
+        if (libxl_pipe(ctx, notify_pipe)) {
+            ret = ERROR_FAIL;
+            goto error_out;
+        }
+        autoconnect_console_how_buf.callback = autoconnect_console;
+        autoconnect_console_how_buf.for_callback = &notify_pipe[1];
+        autoconnect_console_how = &autoconnect_console_how_buf;
+    }else{
+        autoconnect_console_how = 0;
+    }
+
+    if ( restoring ) {
+        libxl_domain_restore_params params;
+
+        libxl_domain_restore_params_init(&params);
+
+        params.checkpointed_stream = dom_info->checkpointed_stream;
+        params.stream_version =
+            (hdr.mandatory_flags & XL_MANDATORY_FLAG_STREAMv2) ? 2 : 1;
+        params.colo_proxy_script = dom_info->colo_proxy_script;
+
+        ret = libxl_domain_create_restore(ctx, &d_config,
+                                          &domid, restore_fd,
+                                          send_back_fd, &params,
+                                          0, autoconnect_console_how);
+
+        libxl_domain_restore_params_dispose(&params);
+
+        /*
+         * On subsequent reboot etc we should create the domain, not
+         * restore/migrate-receive it again.
+         */
+        restoring = 0;
+    } else if (domid_soft_reset != INVALID_DOMID) {
+        /* Do soft reset. */
+        ret = libxl_domain_soft_reset(ctx, &d_config, domid_soft_reset,
+                                      0, autoconnect_console_how);
+        domid = domid_soft_reset;
+        domid_soft_reset = INVALID_DOMID;
+    } else {
+        ret = libxl_domain_create_new(ctx, &d_config, &domid,
+                                      0, autoconnect_console_how);
+    }
+    if ( ret )
+        goto error_out;
+
+    release_lock();
+
+    if (restore_fd_to_close >= 0) {
+        if (close(restore_fd_to_close))
+            fprintf(stderr, "Failed to close restoring file, fd %d, errno %d\n",
+                    restore_fd_to_close, errno);
+        restore_fd_to_close = -1;
+    }
+
+    if (autoconnect_console_how) {
+        char buf[1];
+        int r;
+
+        /* Try to get notification from xenconsole. Just move on if
+         * error occurs -- it's only minor annoyance if console
+         * doesn't show up.
+         */
+        do {
+            r = read(notify_pipe[0], buf, 1);
+        } while (r == -1 && errno == EINTR);
+
+        if (r == -1)
+            fprintf(stderr,
+                    "Failed to get notification from xenconsole: %s\n",
+                    strerror(errno));
+        else if (r == 0)
+            fprintf(stderr, "Got EOF from xenconsole notification fd\n");
+        else if (r == 1 && buf[0] != 0x00)
+            fprintf(stderr, "Got unexpected response from xenconsole: %#x\n",
+                    buf[0]);
+
+        close(notify_pipe[0]);
+        close(notify_pipe[1]);
+        notify_pipe[0] = notify_pipe[1] = -1;
+    }
+
+    if (!paused)
+        libxl_domain_unpause(ctx, domid);
+
+    ret = domid; /* caller gets success in parent */
+    if (!daemonize && !monitor)
+        goto out;
+
+    if (dom_info->vnc)
+        autoconnect_vncviewer(domid, vncautopass);
+
+    if (need_daemon) {
+        char *name;
+
+        xasprintf(&name, "xl-%s", d_config.c_info.name);
+        ret = do_daemonize(name, NULL);
+        free(name);
+        if (ret) {
+            ret = (ret == 1) ? domid : ret;
+            goto out;
+        }
+        need_daemon = 0;
+    }
+    LOG("Waiting for domain %s (domid %u) to die [pid %ld]",
+        d_config.c_info.name, domid, (long)getpid());
+
+    ret = libxl_evenable_domain_death(ctx, domid, 0, &deathw);
+    if (ret) goto out;
+
+    if (!diskws) {
+        diskws = xmalloc(sizeof(*diskws) * d_config.num_disks);
+        for (i = 0; i < d_config.num_disks; i++)
+            diskws[i] = NULL;
+        num_diskws = d_config.num_disks;
+    }
+    for (i = 0; i < num_diskws; i++) {
+        if (d_config.disks[i].removable) {
+            ret = libxl_evenable_disk_eject(ctx, domid, d_config.disks[i].vdev,
+                                            0, &diskws[i]);
+            if (ret) goto out;
+        }
+    }
+    while (1) {
+        libxl_event *event;
+        ret = domain_wait_event(domid, &event);
+        if (ret) goto out;
+
+        switch (event->type) {
+
+        case LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN:
+            LOG("Domain %u has shut down, reason code %d 0x%x", domid,
+                event->u.domain_shutdown.shutdown_reason,
+                event->u.domain_shutdown.shutdown_reason);
+            switch (handle_domain_death(&domid, event, &d_config)) {
+            case DOMAIN_RESTART_SOFT_RESET:
+                domid_soft_reset = domid;
+                domid = INVALID_DOMID;
+                /* fall through */
+            case DOMAIN_RESTART_RENAME:
+                if (domid_soft_reset == INVALID_DOMID &&
+                    !preserve_domain(&domid, event, &d_config)) {
+                    libxl_event_free(ctx, event);
+                    /* If we fail then exit leaving the old domain in place. */
+                    ret = -1;
+                    goto out;
+                }
+
+                /* Otherwise fall through and restart. */
+            case DOMAIN_RESTART_NORMAL:
+                libxl_event_free(ctx, event);
+                libxl_evdisable_domain_death(ctx, deathw);
+                deathw = NULL;
+                evdisable_disk_ejects(diskws, num_diskws);
+                free(diskws);
+                diskws = NULL;
+                num_diskws = 0;
+                /* discard any other events which may have been generated */
+                while (!(ret = libxl_event_check(ctx, &event,
+                                                 LIBXL_EVENTMASK_ALL, 0,0))) {
+                    libxl_event_free(ctx, event);
+                }
+                if (ret != ERROR_NOT_READY) {
+                    LOG("warning, libxl_event_check (cleanup) failed (rc=%d)",
+                        ret);
+                }
+
+                /*
+                 * Do not attempt to reconnect if we come round again due to a
+                 * guest reboot -- the stdin/out will be disconnected by then.
+                 */
+                dom_info->console_autoconnect = 0;
+
+                /* Some settings only make sense on first boot. */
+                paused = 0;
+                if (common_domname
+                    && strcmp(d_config.c_info.name, common_domname)) {
+                    d_config.c_info.name = strdup(common_domname);
+                }
+
+                /*
+                 * XXX FIXME: If this sleep is not there then domain
+                 * re-creation fails sometimes.
+                 */
+                LOG("Done. Rebooting now");
+                sleep(2);
+                goto start;
+
+            case DOMAIN_RESTART_NONE:
+                LOG("Done. Exiting now");
+                libxl_event_free(ctx, event);
+                ret = 0;
+                goto out;
+
+            default:
+                abort();
+            }
+
+        case LIBXL_EVENT_TYPE_DOMAIN_DEATH:
+            LOG("Domain %u has been destroyed.", domid);
+            libxl_event_free(ctx, event);
+            ret = 0;
+            goto out;
+
+        case LIBXL_EVENT_TYPE_DISK_EJECT:
+            /* XXX what is this for? */
+            libxl_cdrom_insert(ctx, domid, &event->u.disk_eject.disk, NULL);
+            break;
+
+        default:;
+            char *evstr = libxl_event_to_json(ctx, event);
+            LOG("warning, got unexpected event type %d, event=%s",
+                event->type, evstr);
+            free(evstr);
+        }
+
+        libxl_event_free(ctx, event);
+    }
+
+error_out:
+    release_lock();
+    if (libxl_domid_valid_guest(domid)) {
+        libxl_domain_destroy(ctx, domid, 0);
+        domid = INVALID_DOMID;
+    }
+
+out:
+    if (restore_fd_to_close >= 0) {
+        if (close(restore_fd_to_close))
+            fprintf(stderr, "Failed to close restoring file, fd %d, errno %d\n",
+                    restore_fd_to_close, errno);
+        restore_fd_to_close = -1;
+    }
+
+    if (logfile != 2)
+        close(logfile);
+
+    libxl_domain_config_dispose(&d_config);
+
+    free(config_data);
+
+    console_child_report(child_console);
+
+    if (deathw)
+        libxl_evdisable_domain_death(ctx, deathw);
+    if (diskws) {
+        evdisable_disk_ejects(diskws, d_config.num_disks);
+        free(diskws);
+    }
+
+    /*
+     * If we have daemonized then do not return to the caller -- this has
+     * already happened in the parent.
+     */
+    if ( daemonize && !need_daemon )
+        exit(ret);
+
+    return ret;
+}
+
+int main_create(int argc, char **argv)
+{
+    const char *filename = NULL;
+    struct domain_create dom_info;
+    int paused = 0, debug = 0, daemonize = 1, console_autoconnect = 0,
+        quiet = 0, monitor = 1, vnc = 0, vncautopass = 0;
+    int opt, rc;
+    static struct option opts[] = {
+        {"dryrun", 0, 0, 'n'},
+        {"quiet", 0, 0, 'q'},
+        {"defconfig", 1, 0, 'f'},
+        {"vncviewer", 0, 0, 'V'},
+        {"vncviewer-autopass", 0, 0, 'A'},
+        COMMON_LONG_OPTS
+    };
+
+    dom_info.extra_config = NULL;
+
+    if (argv[1] && argv[1][0] != '-' && !strchr(argv[1], '=')) {
+        filename = argv[1];
+        argc--; argv++;
+    }
+
+    SWITCH_FOREACH_OPT(opt, "Fnqf:pcdeVA", opts, "create", 0) {
+    case 'f':
+        filename = optarg;
+        break;
+    case 'p':
+        paused = 1;
+        break;
+    case 'c':
+        console_autoconnect = 1;
+        break;
+    case 'd':
+        debug = 1;
+        break;
+    case 'F':
+        daemonize = 0;
+        break;
+    case 'e':
+        daemonize = 0;
+        monitor = 0;
+        break;
+    case 'n':
+        dryrun_only = 1;
+        break;
+    case 'q':
+        quiet = 1;
+        break;
+    case 'V':
+        vnc = 1;
+        break;
+    case 'A':
+        vnc = vncautopass = 1;
+        break;
+    }
+
+    memset(&dom_info, 0, sizeof(dom_info));
+
+    for (; optind < argc; optind++) {
+        if (strchr(argv[optind], '=') != NULL) {
+            xstring_realloc_append(&dom_info.extra_config, argv[optind]);
+            xstring_realloc_append(&dom_info.extra_config, "\n");
+        } else if (!filename) {
+            filename = argv[optind];
+        } else {
+            help("create");
+            free(dom_info.extra_config);
+            return 2;
+        }
+    }
+
+    dom_info.debug = debug;
+    dom_info.daemonize = daemonize;
+    dom_info.monitor = monitor;
+    dom_info.paused = paused;
+    dom_info.dryrun = dryrun_only;
+    dom_info.quiet = quiet;
+    dom_info.config_file = filename;
+    dom_info.migrate_fd = -1;
+    dom_info.send_back_fd = -1;
+    dom_info.vnc = vnc;
+    dom_info.vncautopass = vncautopass;
+    dom_info.console_autoconnect = console_autoconnect;
+
+    rc = create_domain(&dom_info);
+    if (rc < 0) {
+        free(dom_info.extra_config);
+        return -rc;
+    }
+
+    free(dom_info.extra_config);
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 27/29] xl: split out save/restore related code
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (25 preceding siblings ...)
  2017-02-24 16:13 ` [PATCH 26/29] xl: split out vm lifecycle control functions Wei Liu
@ 2017-02-24 16:13 ` Wei Liu
  2017-02-27 16:01   ` Ian Jackson
  2017-02-24 16:13 ` [PATCH 28/29] xl: split out migration " Wei Liu
  2017-02-24 16:13 ` [PATCH 29/29] xl: merge xl_cmdimpl.c into xl.c Wei Liu
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:13 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Add some function declarations to xl.h because they are now needed in
multiple files.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile         |   2 +-
 tools/xl/xl.h             |   6 +
 tools/xl/xl_cmdimpl.c     | 227 --------------------------------------
 tools/xl/xl_saverestore.c | 273 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 280 insertions(+), 228 deletions(-)
 create mode 100644 tools/xl/xl_saverestore.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index 0f966684be..9982b936c4 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -20,7 +20,7 @@ XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
 XL_OBJS += xl_vtpm.o xl_block.o xl_nic.o xl_usb.o
 XL_OBJS += xl_sched.o xl_pci.o xl_vcpu.o xl_cd.o xl_mem.o
 XL_OBJS += xl_psr.o xl_info.o xl_console.o xl_misc.o
-XL_OBJS += xl_vmcontrol.o
+XL_OBJS += xl_vmcontrol.o xl_saverestore.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl.h b/tools/xl/xl.h
index 62d010076b..65b89ce717 100644
--- a/tools/xl/xl.h
+++ b/tools/xl/xl.h
@@ -96,6 +96,12 @@ struct save_file_header {
 
 #define SAVEFILE_BYTEORDER_VALUE ((uint32_t)0x01020304UL)
 
+void save_domain_core_begin(uint32_t domid,
+                            const char *override_config_file,
+                            uint8_t **config_data_r,
+                            int *config_len_r);
+void save_domain_core_writeconfig(int fd, const char *source,
+                                  const uint8_t *config_data, int config_len);
 
 /*
  * The xl process should always return either EXIT_SUCCESS or
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index b3a17d5fa6..c41ae31814 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -99,133 +99,6 @@ void help(const char *command)
 }
 
 #ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
-static void save_domain_core_begin(uint32_t domid,
-                                   const char *override_config_file,
-                                   uint8_t **config_data_r,
-                                   int *config_len_r)
-{
-    int rc;
-    libxl_domain_config d_config;
-    char *config_c = 0;
-
-    /* configuration file in optional data: */
-
-    libxl_domain_config_init(&d_config);
-
-    if (override_config_file) {
-        void *config_v = 0;
-        rc = libxl_read_file_contents(ctx, override_config_file,
-                                      &config_v, config_len_r);
-        if (rc) {
-            fprintf(stderr, "unable to read overridden config file\n");
-            exit(EXIT_FAILURE);
-        }
-        parse_config_data(override_config_file, config_v, *config_len_r,
-                          &d_config);
-        free(config_v);
-    } else {
-        rc = libxl_retrieve_domain_configuration(ctx, domid, &d_config);
-        if (rc) {
-            fprintf(stderr, "unable to retrieve domain configuration\n");
-            exit(EXIT_FAILURE);
-        }
-    }
-
-    config_c = libxl_domain_config_to_json(ctx, &d_config);
-    if (!config_c) {
-        fprintf(stderr, "unable to convert config file to JSON\n");
-        exit(EXIT_FAILURE);
-    }
-    *config_data_r = (uint8_t *)config_c;
-    *config_len_r = strlen(config_c) + 1; /* including trailing '\0' */
-
-    libxl_domain_config_dispose(&d_config);
-}
-
-static void save_domain_core_writeconfig(int fd, const char *source,
-                                  const uint8_t *config_data, int config_len)
-{
-    struct save_file_header hdr;
-    uint8_t *optdata_begin;
-    union { uint32_t u32; char b[4]; } u32buf;
-
-    memset(&hdr, 0, sizeof(hdr));
-    memcpy(hdr.magic, savefileheader_magic, sizeof(hdr.magic));
-    hdr.byteorder = SAVEFILE_BYTEORDER_VALUE;
-    hdr.mandatory_flags = XL_MANDATORY_FLAG_STREAMv2;
-
-    optdata_begin= 0;
-
-#define ADD_OPTDATA(ptr, len) ({                                            \
-    if ((len)) {                                                        \
-        hdr.optional_data_len += (len);                                 \
-        optdata_begin = xrealloc(optdata_begin, hdr.optional_data_len); \
-        memcpy(optdata_begin + hdr.optional_data_len - (len),           \
-               (ptr), (len));                                           \
-    }                                                                   \
-                          })
-
-    u32buf.u32 = config_len;
-    ADD_OPTDATA(u32buf.b,    4);
-    ADD_OPTDATA(config_data, config_len);
-    if (config_len)
-        hdr.mandatory_flags |= XL_MANDATORY_FLAG_JSON;
-
-    /* that's the optional data */
-
-    CHK_ERRNOVAL(libxl_write_exactly(
-                     ctx, fd, &hdr, sizeof(hdr), source, "header"));
-    CHK_ERRNOVAL(libxl_write_exactly(
-                     ctx, fd, optdata_begin, hdr.optional_data_len,
-                     source, "header"));
-
-    free(optdata_begin);
-
-    fprintf(stderr, "Saving to %s new xl format (info"
-            " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
-            source, hdr.mandatory_flags, hdr.optional_flags,
-            hdr.optional_data_len);
-}
-
-static int save_domain(uint32_t domid, const char *filename, int checkpoint,
-                            int leavepaused, const char *override_config_file)
-{
-    int fd;
-    uint8_t *config_data;
-    int config_len;
-
-    save_domain_core_begin(domid, override_config_file,
-                           &config_data, &config_len);
-
-    if (!config_len) {
-        fputs(" Savefile will not contain xl domain config\n", stderr);
-    }
-
-    fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
-    if (fd < 0) {
-        fprintf(stderr, "Failed to open temp file %s for writing\n", filename);
-        exit(EXIT_FAILURE);
-    }
-
-    save_domain_core_writeconfig(fd, filename, config_data, config_len);
-
-    int rc = libxl_domain_suspend(ctx, domid, fd, 0, NULL);
-    close(fd);
-
-    if (rc < 0) {
-        fprintf(stderr, "Failed to save domain, resuming domain\n");
-        libxl_domain_resume(ctx, domid, 1, 0);
-    }
-    else if (leavepaused || checkpoint) {
-        if (leavepaused)
-            libxl_domain_pause(ctx, domid);
-        libxl_domain_resume(ctx, domid, 1, 0);
-    }
-    else
-        libxl_domain_destroy(ctx, domid, 0);
-
-    exit(rc < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
-}
 
 static pid_t create_migration_child(const char *rune, int *send_fd,
                                         int *recv_fd)
@@ -667,74 +540,6 @@ static void migrate_receive(int debug, int daemonize, int monitor,
     exit(EXIT_SUCCESS);
 }
 
-int main_restore(int argc, char **argv)
-{
-    const char *checkpoint_file = NULL;
-    const char *config_file = NULL;
-    struct domain_create dom_info;
-    int paused = 0, debug = 0, daemonize = 1, monitor = 1,
-        console_autoconnect = 0, vnc = 0, vncautopass = 0;
-    int opt, rc;
-    static struct option opts[] = {
-        {"vncviewer", 0, 0, 'V'},
-        {"vncviewer-autopass", 0, 0, 'A'},
-        COMMON_LONG_OPTS
-    };
-
-    SWITCH_FOREACH_OPT(opt, "FcpdeVA", opts, "restore", 1) {
-    case 'c':
-        console_autoconnect = 1;
-        break;
-    case 'p':
-        paused = 1;
-        break;
-    case 'd':
-        debug = 1;
-        break;
-    case 'F':
-        daemonize = 0;
-        break;
-    case 'e':
-        daemonize = 0;
-        monitor = 0;
-        break;
-    case 'V':
-        vnc = 1;
-        break;
-    case 'A':
-        vnc = vncautopass = 1;
-        break;
-    }
-
-    if (argc-optind == 1) {
-        checkpoint_file = argv[optind];
-    } else if (argc-optind == 2) {
-        config_file = argv[optind];
-        checkpoint_file = argv[optind + 1];
-    } else {
-        help("restore");
-        return EXIT_FAILURE;
-    }
-
-    memset(&dom_info, 0, sizeof(dom_info));
-    dom_info.debug = debug;
-    dom_info.daemonize = daemonize;
-    dom_info.monitor = monitor;
-    dom_info.paused = paused;
-    dom_info.config_file = config_file;
-    dom_info.restore_file = checkpoint_file;
-    dom_info.migrate_fd = -1;
-    dom_info.send_back_fd = -1;
-    dom_info.vnc = vnc;
-    dom_info.vncautopass = vncautopass;
-    dom_info.console_autoconnect = console_autoconnect;
-
-    rc = create_domain(&dom_info);
-    if (rc < 0)
-        return EXIT_FAILURE;
-
-    return EXIT_SUCCESS;
-}
 
 int main_migrate_receive(int argc, char **argv)
 {
@@ -785,38 +590,6 @@ int main_migrate_receive(int argc, char **argv)
     return EXIT_SUCCESS;
 }
 
-int main_save(int argc, char **argv)
-{
-    uint32_t domid;
-    const char *filename;
-    const char *config_filename = NULL;
-    int checkpoint = 0;
-    int leavepaused = 0;
-    int opt;
-
-    SWITCH_FOREACH_OPT(opt, "cp", NULL, "save", 2) {
-    case 'c':
-        checkpoint = 1;
-        break;
-    case 'p':
-        leavepaused = 1;
-        break;
-    }
-
-    if (argc-optind > 3) {
-        help("save");
-        return EXIT_FAILURE;
-    }
-
-    domid = xfind_domain(argv[optind]);
-    filename = argv[optind + 1];
-    if ( argc - optind >= 3 )
-        config_filename = argv[optind + 2];
-
-    save_domain(domid, filename, checkpoint, leavepaused, config_filename);
-    return EXIT_SUCCESS;
-}
-
 int main_migrate(int argc, char **argv)
 {
     uint32_t domid;
diff --git a/tools/xl/xl_saverestore.c b/tools/xl/xl_saverestore.c
new file mode 100644
index 0000000000..918c189af0
--- /dev/null
+++ b/tools/xl/xl_saverestore.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
+
+void save_domain_core_begin(uint32_t domid,
+                            const char *override_config_file,
+                            uint8_t **config_data_r,
+                            int *config_len_r)
+{
+    int rc;
+    libxl_domain_config d_config;
+    char *config_c = 0;
+
+    /* configuration file in optional data: */
+
+    libxl_domain_config_init(&d_config);
+
+    if (override_config_file) {
+        void *config_v = 0;
+        rc = libxl_read_file_contents(ctx, override_config_file,
+                                      &config_v, config_len_r);
+        if (rc) {
+            fprintf(stderr, "unable to read overridden config file\n");
+            exit(EXIT_FAILURE);
+        }
+        parse_config_data(override_config_file, config_v, *config_len_r,
+                          &d_config);
+        free(config_v);
+    } else {
+        rc = libxl_retrieve_domain_configuration(ctx, domid, &d_config);
+        if (rc) {
+            fprintf(stderr, "unable to retrieve domain configuration\n");
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    config_c = libxl_domain_config_to_json(ctx, &d_config);
+    if (!config_c) {
+        fprintf(stderr, "unable to convert config file to JSON\n");
+        exit(EXIT_FAILURE);
+    }
+    *config_data_r = (uint8_t *)config_c;
+    *config_len_r = strlen(config_c) + 1; /* including trailing '\0' */
+
+    libxl_domain_config_dispose(&d_config);
+}
+
+void save_domain_core_writeconfig(int fd, const char *source,
+                                  const uint8_t *config_data, int config_len)
+{
+    struct save_file_header hdr;
+    uint8_t *optdata_begin;
+    union { uint32_t u32; char b[4]; } u32buf;
+
+    memset(&hdr, 0, sizeof(hdr));
+    memcpy(hdr.magic, savefileheader_magic, sizeof(hdr.magic));
+    hdr.byteorder = SAVEFILE_BYTEORDER_VALUE;
+    hdr.mandatory_flags = XL_MANDATORY_FLAG_STREAMv2;
+
+    optdata_begin= 0;
+
+#define ADD_OPTDATA(ptr, len) ({                                            \
+    if ((len)) {                                                        \
+        hdr.optional_data_len += (len);                                 \
+        optdata_begin = xrealloc(optdata_begin, hdr.optional_data_len); \
+        memcpy(optdata_begin + hdr.optional_data_len - (len),           \
+               (ptr), (len));                                           \
+    }                                                                   \
+                          })
+
+    u32buf.u32 = config_len;
+    ADD_OPTDATA(u32buf.b,    4);
+    ADD_OPTDATA(config_data, config_len);
+    if (config_len)
+        hdr.mandatory_flags |= XL_MANDATORY_FLAG_JSON;
+
+    /* that's the optional data */
+
+    CHK_ERRNOVAL(libxl_write_exactly(
+                     ctx, fd, &hdr, sizeof(hdr), source, "header"));
+    CHK_ERRNOVAL(libxl_write_exactly(
+                     ctx, fd, optdata_begin, hdr.optional_data_len,
+                     source, "header"));
+
+    free(optdata_begin);
+
+    fprintf(stderr, "Saving to %s new xl format (info"
+            " 0x%"PRIx32"/0x%"PRIx32"/%"PRIu32")\n",
+            source, hdr.mandatory_flags, hdr.optional_flags,
+            hdr.optional_data_len);
+}
+
+static int save_domain(uint32_t domid, const char *filename, int checkpoint,
+                            int leavepaused, const char *override_config_file)
+{
+    int fd;
+    uint8_t *config_data;
+    int config_len;
+
+    save_domain_core_begin(domid, override_config_file,
+                           &config_data, &config_len);
+
+    if (!config_len) {
+        fputs(" Savefile will not contain xl domain config\n", stderr);
+    }
+
+    fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+    if (fd < 0) {
+        fprintf(stderr, "Failed to open temp file %s for writing\n", filename);
+        exit(EXIT_FAILURE);
+    }
+
+    save_domain_core_writeconfig(fd, filename, config_data, config_len);
+
+    int rc = libxl_domain_suspend(ctx, domid, fd, 0, NULL);
+    close(fd);
+
+    if (rc < 0) {
+        fprintf(stderr, "Failed to save domain, resuming domain\n");
+        libxl_domain_resume(ctx, domid, 1, 0);
+    }
+    else if (leavepaused || checkpoint) {
+        if (leavepaused)
+            libxl_domain_pause(ctx, domid);
+        libxl_domain_resume(ctx, domid, 1, 0);
+    }
+    else
+        libxl_domain_destroy(ctx, domid, 0);
+
+    exit(rc < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+int main_restore(int argc, char **argv)
+{
+    const char *checkpoint_file = NULL;
+    const char *config_file = NULL;
+    struct domain_create dom_info;
+    int paused = 0, debug = 0, daemonize = 1, monitor = 1,
+        console_autoconnect = 0, vnc = 0, vncautopass = 0;
+    int opt, rc;
+    static struct option opts[] = {
+        {"vncviewer", 0, 0, 'V'},
+        {"vncviewer-autopass", 0, 0, 'A'},
+        COMMON_LONG_OPTS
+    };
+
+    SWITCH_FOREACH_OPT(opt, "FcpdeVA", opts, "restore", 1) {
+    case 'c':
+        console_autoconnect = 1;
+        break;
+    case 'p':
+        paused = 1;
+        break;
+    case 'd':
+        debug = 1;
+        break;
+    case 'F':
+        daemonize = 0;
+        break;
+    case 'e':
+        daemonize = 0;
+        monitor = 0;
+        break;
+    case 'V':
+        vnc = 1;
+        break;
+    case 'A':
+        vnc = vncautopass = 1;
+        break;
+    }
+
+    if (argc-optind == 1) {
+        checkpoint_file = argv[optind];
+    } else if (argc-optind == 2) {
+        config_file = argv[optind];
+        checkpoint_file = argv[optind + 1];
+    } else {
+        help("restore");
+        return EXIT_FAILURE;
+    }
+
+    memset(&dom_info, 0, sizeof(dom_info));
+    dom_info.debug = debug;
+    dom_info.daemonize = daemonize;
+    dom_info.monitor = monitor;
+    dom_info.paused = paused;
+    dom_info.config_file = config_file;
+    dom_info.restore_file = checkpoint_file;
+    dom_info.migrate_fd = -1;
+    dom_info.send_back_fd = -1;
+    dom_info.vnc = vnc;
+    dom_info.vncautopass = vncautopass;
+    dom_info.console_autoconnect = console_autoconnect;
+
+    rc = create_domain(&dom_info);
+    if (rc < 0)
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+int main_save(int argc, char **argv)
+{
+    uint32_t domid;
+    const char *filename;
+    const char *config_filename = NULL;
+    int checkpoint = 0;
+    int leavepaused = 0;
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "cp", NULL, "save", 2) {
+    case 'c':
+        checkpoint = 1;
+        break;
+    case 'p':
+        leavepaused = 1;
+        break;
+    }
+
+    if (argc-optind > 3) {
+        help("save");
+        return EXIT_FAILURE;
+    }
+
+    domid = xfind_domain(argv[optind]);
+    filename = argv[optind + 1];
+    if ( argc - optind >= 3 )
+        config_filename = argv[optind + 2];
+
+    save_domain(domid, filename, checkpoint, leavepaused, config_filename);
+    return EXIT_SUCCESS;
+}
+
+#endif /* LIBXL_HAVE_NO_SUSPEND_RESUME */
+
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 28/29] xl: split out migration related code
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (26 preceding siblings ...)
  2017-02-24 16:13 ` [PATCH 27/29] xl: split out save/restore related code Wei Liu
@ 2017-02-24 16:13 ` Wei Liu
  2017-02-27 15:59   ` Ian Jackson
  2017-02-24 16:13 ` [PATCH 29/29] xl: merge xl_cmdimpl.c into xl.c Wei Liu
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:13 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Include COLO / Remus code because they are built on top of the existing
migration protocol.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   2 +-
 tools/xl/xl_cmdimpl.c | 715 -----------------------------------------------
 tools/xl/xl_migrate.c | 754 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 755 insertions(+), 716 deletions(-)
 create mode 100644 tools/xl/xl_migrate.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index 9982b936c4..8c30fdcf9e 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -20,7 +20,7 @@ XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
 XL_OBJS += xl_vtpm.o xl_block.o xl_nic.o xl_usb.o
 XL_OBJS += xl_sched.o xl_pci.o xl_vcpu.o xl_cd.o xl_mem.o
 XL_OBJS += xl_psr.o xl_info.o xl_console.o xl_misc.o
-XL_OBJS += xl_vmcontrol.o xl_saverestore.o
+XL_OBJS += xl_vmcontrol.o xl_saverestore.o xl_migrate.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index c41ae31814..bd7f8edb0a 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -98,721 +98,6 @@ void help(const char *command)
     }
 }
 
-#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
-
-static pid_t create_migration_child(const char *rune, int *send_fd,
-                                        int *recv_fd)
-{
-    int sendpipe[2], recvpipe[2];
-    pid_t child;
-
-    if (!rune || !send_fd || !recv_fd)
-        return -1;
-
-    MUST( libxl_pipe(ctx, sendpipe) );
-    MUST( libxl_pipe(ctx, recvpipe) );
-
-    child = xl_fork(child_migration, "migration transport process");
-
-    if (!child) {
-        dup2(sendpipe[0], 0);
-        dup2(recvpipe[1], 1);
-        close(sendpipe[0]); close(sendpipe[1]);
-        close(recvpipe[0]); close(recvpipe[1]);
-        execlp("sh","sh","-c",rune,(char*)0);
-        perror("failed to exec sh");
-        exit(EXIT_FAILURE);
-    }
-
-    close(sendpipe[0]);
-    close(recvpipe[1]);
-    *send_fd = sendpipe[1];
-    *recv_fd = recvpipe[0];
-
-    /* if receiver dies, we get an error and can clean up
-       rather than just dying */
-    signal(SIGPIPE, SIG_IGN);
-
-    return child;
-}
-
-static int migrate_read_fixedmessage(int fd, const void *msg, int msgsz,
-                                     const char *what, const char *rune) {
-    char buf[msgsz];
-    const char *stream;
-    int rc;
-
-    stream = rune ? "migration receiver stream" : "migration stream";
-    rc = libxl_read_exactly(ctx, fd, buf, msgsz, stream, what);
-    if (rc) return 1;
-
-    if (memcmp(buf, msg, msgsz)) {
-        fprintf(stderr, "%s contained unexpected data instead of %s\n",
-                stream, what);
-        if (rune)
-            fprintf(stderr, "(command run was: %s )\n", rune);
-        return 1;
-    }
-    return 0;
-}
-
-static void migration_child_report(int recv_fd) {
-    pid_t child;
-    int status, sr;
-    struct timeval now, waituntil, timeout;
-    static const struct timeval pollinterval = { 0, 1000 }; /* 1ms */
-
-    if (!xl_child_pid(child_migration)) return;
-
-    CHK_SYSCALL(gettimeofday(&waituntil, 0));
-    waituntil.tv_sec += 2;
-
-    for (;;) {
-        pid_t migration_child = xl_child_pid(child_migration);
-        child = xl_waitpid(child_migration, &status, WNOHANG);
-
-        if (child == migration_child) {
-            if (status)
-                xl_report_child_exitstatus(XTL_INFO, child_migration,
-                                           migration_child, status);
-            break;
-        }
-        if (child == -1) {
-            fprintf(stderr, "wait for migration child [%ld] failed: %s\n",
-                    (long)migration_child, strerror(errno));
-            break;
-        }
-        assert(child == 0);
-
-        CHK_SYSCALL(gettimeofday(&now, 0));
-        if (timercmp(&now, &waituntil, >)) {
-            fprintf(stderr, "migration child [%ld] not exiting, no longer"
-                    " waiting (exit status will be unreported)\n",
-                    (long)migration_child);
-            break;
-        }
-        timersub(&waituntil, &now, &timeout);
-
-        if (recv_fd >= 0) {
-            fd_set readfds, exceptfds;
-            FD_ZERO(&readfds);
-            FD_ZERO(&exceptfds);
-            FD_SET(recv_fd, &readfds);
-            FD_SET(recv_fd, &exceptfds);
-            sr = select(recv_fd+1, &readfds,0,&exceptfds, &timeout);
-        } else {
-            if (timercmp(&timeout, &pollinterval, >))
-                timeout = pollinterval;
-            sr = select(0,0,0,0, &timeout);
-        }
-        if (sr > 0) {
-            recv_fd = -1;
-        } else if (sr == 0) {
-        } else if (sr == -1) {
-            if (errno != EINTR) {
-                fprintf(stderr, "migration child [%ld] exit wait select"
-                        " failed unexpectedly: %s\n",
-                        (long)migration_child, strerror(errno));
-                break;
-            }
-        }
-    }
-}
-
-static void migrate_do_preamble(int send_fd, int recv_fd, pid_t child,
-                                uint8_t *config_data, int config_len,
-                                const char *rune)
-{
-    int rc = 0;
-
-    if (send_fd < 0 || recv_fd < 0) {
-        fprintf(stderr, "migrate_do_preamble: invalid file descriptors\n");
-        exit(EXIT_FAILURE);
-    }
-
-    rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_banner,
-                                   sizeof(migrate_receiver_banner)-1,
-                                   "banner", rune);
-    if (rc) {
-        close(send_fd);
-        migration_child_report(recv_fd);
-        exit(EXIT_FAILURE);
-    }
-
-    save_domain_core_writeconfig(send_fd, "migration stream",
-                                 config_data, config_len);
-
-}
-
-static void migrate_domain(uint32_t domid, const char *rune, int debug,
-                           const char *override_config_file)
-{
-    pid_t child = -1;
-    int rc;
-    int send_fd = -1, recv_fd = -1;
-    char *away_domname;
-    char rc_buf;
-    uint8_t *config_data;
-    int config_len, flags = LIBXL_SUSPEND_LIVE;
-
-    save_domain_core_begin(domid, override_config_file,
-                           &config_data, &config_len);
-
-    if (!config_len) {
-        fprintf(stderr, "No config file stored for running domain and "
-                "none supplied - cannot migrate.\n");
-        exit(EXIT_FAILURE);
-    }
-
-    child = create_migration_child(rune, &send_fd, &recv_fd);
-
-    migrate_do_preamble(send_fd, recv_fd, child, config_data, config_len,
-                        rune);
-
-    xtl_stdiostream_adjust_flags(logger, XTL_STDIOSTREAM_HIDE_PROGRESS, 0);
-
-    if (debug)
-        flags |= LIBXL_SUSPEND_DEBUG;
-    rc = libxl_domain_suspend(ctx, domid, send_fd, flags, NULL);
-    if (rc) {
-        fprintf(stderr, "migration sender: libxl_domain_suspend failed"
-                " (rc=%d)\n", rc);
-        if (rc == ERROR_GUEST_TIMEDOUT)
-            goto failed_suspend;
-        else
-            goto failed_resume;
-    }
-
-    //fprintf(stderr, "migration sender: Transfer complete.\n");
-    // Should only be printed when debugging as it's a bit messy with
-    // progress indication.
-
-    rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_ready,
-                                   sizeof(migrate_receiver_ready),
-                                   "ready message", rune);
-    if (rc) goto failed_resume;
-
-    xtl_stdiostream_adjust_flags(logger, 0, XTL_STDIOSTREAM_HIDE_PROGRESS);
-
-    /* right, at this point we are about give the destination
-     * permission to rename and resume, so we must first rename the
-     * domain away ourselves */
-
-    fprintf(stderr, "migration sender: Target has acknowledged transfer.\n");
-
-    if (common_domname) {
-        xasprintf(&away_domname, "%s--migratedaway", common_domname);
-        rc = libxl_domain_rename(ctx, domid, common_domname, away_domname);
-        if (rc) goto failed_resume;
-    }
-
-    /* point of no return - as soon as we have tried to say
-     * "go" to the receiver, it's not safe to carry on.  We leave
-     * the domain renamed to %s--migratedaway in case that's helpful.
-     */
-
-    fprintf(stderr, "migration sender: Giving target permission to start.\n");
-
-    rc = libxl_write_exactly(ctx, send_fd,
-                             migrate_permission_to_go,
-                             sizeof(migrate_permission_to_go),
-                             "migration stream", "GO message");
-    if (rc) goto failed_badly;
-
-    rc = migrate_read_fixedmessage(recv_fd, migrate_report,
-                                   sizeof(migrate_report),
-                                   "success/failure report message", rune);
-    if (rc) goto failed_badly;
-
-    rc = libxl_read_exactly(ctx, recv_fd,
-                            &rc_buf, 1,
-                            "migration ack stream", "success/failure status");
-    if (rc) goto failed_badly;
-
-    if (rc_buf) {
-        fprintf(stderr, "migration sender: Target reports startup failure"
-                " (status code %d).\n", rc_buf);
-
-        rc = migrate_read_fixedmessage(recv_fd, migrate_permission_to_go,
-                                       sizeof(migrate_permission_to_go),
-                                       "permission for sender to resume",
-                                       rune);
-        if (rc) goto failed_badly;
-
-        fprintf(stderr, "migration sender: Trying to resume at our end.\n");
-
-        if (common_domname) {
-            libxl_domain_rename(ctx, domid, away_domname, common_domname);
-        }
-        rc = libxl_domain_resume(ctx, domid, 1, 0);
-        if (!rc) fprintf(stderr, "migration sender: Resumed OK.\n");
-
-        fprintf(stderr, "Migration failed due to problems at target.\n");
-        exit(EXIT_FAILURE);
-    }
-
-    fprintf(stderr, "migration sender: Target reports successful startup.\n");
-    libxl_domain_destroy(ctx, domid, 0); /* bang! */
-    fprintf(stderr, "Migration successful.\n");
-    exit(EXIT_SUCCESS);
-
- failed_suspend:
-    close(send_fd);
-    migration_child_report(recv_fd);
-    fprintf(stderr, "Migration failed, failed to suspend at sender.\n");
-    exit(EXIT_FAILURE);
-
- failed_resume:
-    close(send_fd);
-    migration_child_report(recv_fd);
-    fprintf(stderr, "Migration failed, resuming at sender.\n");
-    libxl_domain_resume(ctx, domid, 1, 0);
-    exit(EXIT_FAILURE);
-
- failed_badly:
-    fprintf(stderr,
- "** Migration failed during final handshake **\n"
- "Domain state is now undefined !\n"
- "Please CHECK AT BOTH ENDS for running instances, before renaming and\n"
- " resuming at most one instance.  Two simultaneous instances of the domain\n"
- " would probably result in SEVERE DATA LOSS and it is now your\n"
- " responsibility to avoid that.  Sorry.\n");
-
-    close(send_fd);
-    migration_child_report(recv_fd);
-    exit(EXIT_FAILURE);
-}
-
-static void migrate_receive(int debug, int daemonize, int monitor,
-                            int pause_after_migration,
-                            int send_fd, int recv_fd,
-                            libxl_checkpointed_stream checkpointed,
-                            char *colo_proxy_script)
-{
-    uint32_t domid;
-    int rc, rc2;
-    char rc_buf;
-    char *migration_domname;
-    struct domain_create dom_info;
-
-    signal(SIGPIPE, SIG_IGN);
-    /* if we get SIGPIPE we'd rather just have it as an error */
-
-    fprintf(stderr, "migration target: Ready to receive domain.\n");
-
-    CHK_ERRNOVAL(libxl_write_exactly(
-                     ctx, send_fd, migrate_receiver_banner,
-                     sizeof(migrate_receiver_banner)-1,
-                     "migration ack stream", "banner") );
-
-    memset(&dom_info, 0, sizeof(dom_info));
-    dom_info.debug = debug;
-    dom_info.daemonize = daemonize;
-    dom_info.monitor = monitor;
-    dom_info.paused = 1;
-    dom_info.migrate_fd = recv_fd;
-    dom_info.send_back_fd = send_fd;
-    dom_info.migration_domname_r = &migration_domname;
-    dom_info.checkpointed_stream = checkpointed;
-    dom_info.colo_proxy_script = colo_proxy_script;
-
-    rc = create_domain(&dom_info);
-    if (rc < 0) {
-        fprintf(stderr, "migration target: Domain creation failed"
-                " (code %d).\n", rc);
-        exit(EXIT_FAILURE);
-    }
-
-    domid = rc;
-
-    switch (checkpointed) {
-    case LIBXL_CHECKPOINTED_STREAM_REMUS:
-    case LIBXL_CHECKPOINTED_STREAM_COLO:
-    {
-        const char *ha = checkpointed == LIBXL_CHECKPOINTED_STREAM_COLO ?
-                         "COLO" : "Remus";
-        /* If we are here, it means that the sender (primary) has crashed.
-         * TODO: Split-Brain Check.
-         */
-        fprintf(stderr, "migration target: %s Failover for domain %u\n",
-                ha, domid);
-
-        /*
-         * If domain renaming fails, lets just continue (as we need the domain
-         * to be up & dom names may not matter much, as long as its reachable
-         * over network).
-         *
-         * If domain unpausing fails, destroy domain ? Or is it better to have
-         * a consistent copy of the domain (memory, cpu state, disk)
-         * on atleast one physical host ? Right now, lets just leave the domain
-         * as is and let the Administrator decide (or troubleshoot).
-         */
-        if (migration_domname) {
-            rc = libxl_domain_rename(ctx, domid, migration_domname,
-                                     common_domname);
-            if (rc)
-                fprintf(stderr, "migration target (%s): "
-                        "Failed to rename domain from %s to %s:%d\n",
-                        ha, migration_domname, common_domname, rc);
-        }
-
-        if (checkpointed == LIBXL_CHECKPOINTED_STREAM_COLO)
-            /* The guest is running after failover in COLO mode */
-            exit(rc ? -ERROR_FAIL: 0);
-
-        rc = libxl_domain_unpause(ctx, domid);
-        if (rc)
-            fprintf(stderr, "migration target (%s): "
-                    "Failed to unpause domain %s (id: %u):%d\n",
-                    ha, common_domname, domid, rc);
-
-        exit(rc ? EXIT_FAILURE : EXIT_SUCCESS);
-    }
-    default:
-        /* do nothing */
-        break;
-    }
-
-    fprintf(stderr, "migration target: Transfer complete,"
-            " requesting permission to start domain.\n");
-
-    rc = libxl_write_exactly(ctx, send_fd,
-                             migrate_receiver_ready,
-                             sizeof(migrate_receiver_ready),
-                             "migration ack stream", "ready message");
-    if (rc) exit(EXIT_FAILURE);
-
-    rc = migrate_read_fixedmessage(recv_fd, migrate_permission_to_go,
-                                   sizeof(migrate_permission_to_go),
-                                   "GO message", 0);
-    if (rc) goto perhaps_destroy_notify_rc;
-
-    fprintf(stderr, "migration target: Got permission, starting domain.\n");
-
-    if (migration_domname) {
-        rc = libxl_domain_rename(ctx, domid, migration_domname, common_domname);
-        if (rc) goto perhaps_destroy_notify_rc;
-    }
-
-    if (!pause_after_migration) {
-        rc = libxl_domain_unpause(ctx, domid);
-        if (rc) goto perhaps_destroy_notify_rc;
-    }
-
-    fprintf(stderr, "migration target: Domain started successsfully.\n");
-    rc = 0;
-
- perhaps_destroy_notify_rc:
-    rc2 = libxl_write_exactly(ctx, send_fd,
-                              migrate_report, sizeof(migrate_report),
-                              "migration ack stream",
-                              "success/failure report");
-    if (rc2) exit(EXIT_FAILURE);
-
-    rc_buf = -rc;
-    assert(!!rc_buf == !!rc);
-    rc2 = libxl_write_exactly(ctx, send_fd, &rc_buf, 1,
-                              "migration ack stream",
-                              "success/failure code");
-    if (rc2) exit(EXIT_FAILURE);
-
-    if (rc) {
-        fprintf(stderr, "migration target: Failure, destroying our copy.\n");
-
-        rc2 = libxl_domain_destroy(ctx, domid, 0);
-        if (rc2) {
-            fprintf(stderr, "migration target: Failed to destroy our copy"
-                    " (code %d).\n", rc2);
-            exit(EXIT_FAILURE);
-        }
-
-        fprintf(stderr, "migration target: Cleanup OK, granting sender"
-                " permission to resume.\n");
-
-        rc2 = libxl_write_exactly(ctx, send_fd,
-                                  migrate_permission_to_go,
-                                  sizeof(migrate_permission_to_go),
-                                  "migration ack stream",
-                                  "permission to sender to have domain back");
-        if (rc2) exit(EXIT_FAILURE);
-    }
-
-    exit(EXIT_SUCCESS);
-}
-
-
-int main_migrate_receive(int argc, char **argv)
-{
-    int debug = 0, daemonize = 1, monitor = 1, pause_after_migration = 0;
-    libxl_checkpointed_stream checkpointed = LIBXL_CHECKPOINTED_STREAM_NONE;
-    int opt;
-    char *script = NULL;
-    static struct option opts[] = {
-        {"colo", 0, 0, 0x100},
-        /* It is a shame that the management code for disk is not here. */
-        {"coloft-script", 1, 0, 0x200},
-        COMMON_LONG_OPTS
-    };
-
-    SWITCH_FOREACH_OPT(opt, "Fedrp", opts, "migrate-receive", 0) {
-    case 'F':
-        daemonize = 0;
-        break;
-    case 'e':
-        daemonize = 0;
-        monitor = 0;
-        break;
-    case 'd':
-        debug = 1;
-        break;
-    case 'r':
-        checkpointed = LIBXL_CHECKPOINTED_STREAM_REMUS;
-        break;
-    case 0x100:
-        checkpointed = LIBXL_CHECKPOINTED_STREAM_COLO;
-        break;
-    case 0x200:
-        script = optarg;
-        break;
-    case 'p':
-        pause_after_migration = 1;
-        break;
-    }
-
-    if (argc-optind != 0) {
-        help("migrate-receive");
-        return EXIT_FAILURE;
-    }
-    migrate_receive(debug, daemonize, monitor, pause_after_migration,
-                    STDOUT_FILENO, STDIN_FILENO,
-                    checkpointed, script);
-
-    return EXIT_SUCCESS;
-}
-
-int main_migrate(int argc, char **argv)
-{
-    uint32_t domid;
-    const char *config_filename = NULL;
-    const char *ssh_command = "ssh";
-    char *rune = NULL;
-    char *host;
-    int opt, daemonize = 1, monitor = 1, debug = 0, pause_after_migration = 0;
-    static struct option opts[] = {
-        {"debug", 0, 0, 0x100},
-        {"live", 0, 0, 0x200},
-        COMMON_LONG_OPTS
-    };
-
-    SWITCH_FOREACH_OPT(opt, "FC:s:ep", opts, "migrate", 2) {
-    case 'C':
-        config_filename = optarg;
-        break;
-    case 's':
-        ssh_command = optarg;
-        break;
-    case 'F':
-        daemonize = 0;
-        break;
-    case 'e':
-        daemonize = 0;
-        monitor = 0;
-        break;
-    case 'p':
-        pause_after_migration = 1;
-        break;
-    case 0x100: /* --debug */
-        debug = 1;
-        break;
-    case 0x200: /* --live */
-        /* ignored for compatibility with xm */
-        break;
-    }
-
-    domid = xfind_domain(argv[optind]);
-    host = argv[optind + 1];
-
-    bool pass_tty_arg = progress_use_cr || (isatty(2) > 0);
-
-    if (!ssh_command[0]) {
-        rune= host;
-    } else {
-        char verbose_buf[minmsglevel_default+3];
-        int verbose_len;
-        verbose_buf[0] = ' ';
-        verbose_buf[1] = '-';
-        memset(verbose_buf+2, 'v', minmsglevel_default);
-        verbose_buf[sizeof(verbose_buf)-1] = 0;
-        if (minmsglevel == minmsglevel_default) {
-            verbose_len = 0;
-        } else {
-            verbose_len = (minmsglevel_default - minmsglevel) + 2;
-        }
-        xasprintf(&rune, "exec %s %s xl%s%.*s migrate-receive%s%s%s",
-                  ssh_command, host,
-                  pass_tty_arg ? " -t" : "",
-                  verbose_len, verbose_buf,
-                  daemonize ? "" : " -e",
-                  debug ? " -d" : "",
-                  pause_after_migration ? " -p" : "");
-    }
-
-    migrate_domain(domid, rune, debug, config_filename);
-    return EXIT_SUCCESS;
-}
-#endif
-
-#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
-int main_remus(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt, rc, daemonize = 1;
-    const char *ssh_command = "ssh";
-    char *host = NULL, *rune = NULL;
-    libxl_domain_remus_info r_info;
-    int send_fd = -1, recv_fd = -1;
-    pid_t child = -1;
-    uint8_t *config_data;
-    int config_len;
-
-    memset(&r_info, 0, sizeof(libxl_domain_remus_info));
-
-    SWITCH_FOREACH_OPT(opt, "Fbundi:s:N:ec", NULL, "remus", 2) {
-    case 'i':
-        r_info.interval = atoi(optarg);
-        break;
-    case 'F':
-        libxl_defbool_set(&r_info.allow_unsafe, true);
-        break;
-    case 'b':
-        libxl_defbool_set(&r_info.blackhole, true);
-        break;
-    case 'u':
-        libxl_defbool_set(&r_info.compression, false);
-        break;
-    case 'n':
-        libxl_defbool_set(&r_info.netbuf, false);
-        break;
-    case 'N':
-        r_info.netbufscript = optarg;
-        break;
-    case 'd':
-        libxl_defbool_set(&r_info.diskbuf, false);
-        break;
-    case 's':
-        ssh_command = optarg;
-        break;
-    case 'e':
-        daemonize = 0;
-        break;
-    case 'c':
-        libxl_defbool_set(&r_info.colo, true);
-    }
-
-    domid = xfind_domain(argv[optind]);
-    host = argv[optind + 1];
-
-    /* Defaults */
-    libxl_defbool_setdefault(&r_info.blackhole, false);
-    libxl_defbool_setdefault(&r_info.colo, false);
-    if (!libxl_defbool_val(r_info.colo) && !r_info.interval)
-        r_info.interval = 200;
-
-    if (libxl_defbool_val(r_info.colo)) {
-        if (r_info.interval || libxl_defbool_val(r_info.blackhole) ||
-            !libxl_defbool_is_default(r_info.netbuf) ||
-            !libxl_defbool_is_default(r_info.diskbuf)) {
-            perror("option -c is conflict with -i, -d, -n or -b");
-            exit(-1);
-        }
-
-        if (libxl_defbool_is_default(r_info.compression)) {
-            perror("COLO can't be used with memory compression. "
-                   "Disable memory checkpoint compression now...");
-            libxl_defbool_set(&r_info.compression, false);
-        }
-    }
-
-    if (!r_info.netbufscript) {
-        if (libxl_defbool_val(r_info.colo))
-            r_info.netbufscript = default_colo_proxy_script;
-        else
-            r_info.netbufscript = default_remus_netbufscript;
-    }
-
-    if (libxl_defbool_val(r_info.blackhole)) {
-        send_fd = open("/dev/null", O_RDWR, 0644);
-        if (send_fd < 0) {
-            perror("failed to open /dev/null");
-            exit(EXIT_FAILURE);
-        }
-    } else {
-
-        if (!ssh_command[0]) {
-            rune = host;
-        } else {
-            if (!libxl_defbool_val(r_info.colo)) {
-                xasprintf(&rune, "exec %s %s xl migrate-receive %s %s",
-                          ssh_command, host,
-                          "-r",
-                          daemonize ? "" : " -e");
-            } else {
-                xasprintf(&rune, "exec %s %s xl migrate-receive %s %s %s %s",
-                          ssh_command, host,
-                          "--colo",
-                          r_info.netbufscript ? "--coloft-script" : "",
-                          r_info.netbufscript ? r_info.netbufscript : "",
-                          daemonize ? "" : " -e");
-            }
-        }
-
-        save_domain_core_begin(domid, NULL, &config_data, &config_len);
-
-        if (!config_len) {
-            fprintf(stderr, "No config file stored for running domain and "
-                    "none supplied - cannot start remus.\n");
-            exit(EXIT_FAILURE);
-        }
-
-        child = create_migration_child(rune, &send_fd, &recv_fd);
-
-        migrate_do_preamble(send_fd, recv_fd, child, config_data, config_len,
-                            rune);
-
-        if (ssh_command[0])
-            free(rune);
-    }
-
-    /* Point of no return */
-    rc = libxl_domain_remus_start(ctx, &r_info, domid, send_fd, recv_fd, 0);
-
-    /* check if the domain exists. User may have xl destroyed the
-     * domain to force failover
-     */
-    if (libxl_domain_info(ctx, 0, domid)) {
-        fprintf(stderr, "%s: Primary domain has been destroyed.\n",
-                libxl_defbool_val(r_info.colo) ? "COLO" : "Remus");
-        close(send_fd);
-        return EXIT_SUCCESS;
-    }
-
-    /* If we are here, it means remus setup/domain suspend/backup has
-     * failed. Try to resume the domain and exit gracefully.
-     * TODO: Split-Brain check.
-     */
-    if (rc == ERROR_GUEST_TIMEDOUT)
-        fprintf(stderr, "Failed to suspend domain at primary.\n");
-    else {
-        fprintf(stderr, "%s: Backup failed? resuming domain at primary.\n",
-                libxl_defbool_val(r_info.colo) ? "COLO" : "Remus");
-        libxl_domain_resume(ctx, domid, 1, 0);
-    }
-
-    close(send_fd);
-    return EXIT_FAILURE;
-}
-#endif
-
 /*
  * Local variables:
  * mode: C
diff --git a/tools/xl/xl_migrate.c b/tools/xl/xl_migrate.c
new file mode 100644
index 0000000000..6b5dff2d1a
--- /dev/null
+++ b/tools/xl/xl_migrate.c
@@ -0,0 +1,754 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+extern const char *common_domname;
+
+#ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
+
+static pid_t create_migration_child(const char *rune, int *send_fd,
+                                        int *recv_fd)
+{
+    int sendpipe[2], recvpipe[2];
+    pid_t child;
+
+    if (!rune || !send_fd || !recv_fd)
+        return -1;
+
+    MUST( libxl_pipe(ctx, sendpipe) );
+    MUST( libxl_pipe(ctx, recvpipe) );
+
+    child = xl_fork(child_migration, "migration transport process");
+
+    if (!child) {
+        dup2(sendpipe[0], 0);
+        dup2(recvpipe[1], 1);
+        close(sendpipe[0]); close(sendpipe[1]);
+        close(recvpipe[0]); close(recvpipe[1]);
+        execlp("sh","sh","-c",rune,(char*)0);
+        perror("failed to exec sh");
+        exit(EXIT_FAILURE);
+    }
+
+    close(sendpipe[0]);
+    close(recvpipe[1]);
+    *send_fd = sendpipe[1];
+    *recv_fd = recvpipe[0];
+
+    /* if receiver dies, we get an error and can clean up
+       rather than just dying */
+    signal(SIGPIPE, SIG_IGN);
+
+    return child;
+}
+
+static int migrate_read_fixedmessage(int fd, const void *msg, int msgsz,
+                                     const char *what, const char *rune) {
+    char buf[msgsz];
+    const char *stream;
+    int rc;
+
+    stream = rune ? "migration receiver stream" : "migration stream";
+    rc = libxl_read_exactly(ctx, fd, buf, msgsz, stream, what);
+    if (rc) return 1;
+
+    if (memcmp(buf, msg, msgsz)) {
+        fprintf(stderr, "%s contained unexpected data instead of %s\n",
+                stream, what);
+        if (rune)
+            fprintf(stderr, "(command run was: %s )\n", rune);
+        return 1;
+    }
+    return 0;
+}
+
+static void migration_child_report(int recv_fd) {
+    pid_t child;
+    int status, sr;
+    struct timeval now, waituntil, timeout;
+    static const struct timeval pollinterval = { 0, 1000 }; /* 1ms */
+
+    if (!xl_child_pid(child_migration)) return;
+
+    CHK_SYSCALL(gettimeofday(&waituntil, 0));
+    waituntil.tv_sec += 2;
+
+    for (;;) {
+        pid_t migration_child = xl_child_pid(child_migration);
+        child = xl_waitpid(child_migration, &status, WNOHANG);
+
+        if (child == migration_child) {
+            if (status)
+                xl_report_child_exitstatus(XTL_INFO, child_migration,
+                                           migration_child, status);
+            break;
+        }
+        if (child == -1) {
+            fprintf(stderr, "wait for migration child [%ld] failed: %s\n",
+                    (long)migration_child, strerror(errno));
+            break;
+        }
+        assert(child == 0);
+
+        CHK_SYSCALL(gettimeofday(&now, 0));
+        if (timercmp(&now, &waituntil, >)) {
+            fprintf(stderr, "migration child [%ld] not exiting, no longer"
+                    " waiting (exit status will be unreported)\n",
+                    (long)migration_child);
+            break;
+        }
+        timersub(&waituntil, &now, &timeout);
+
+        if (recv_fd >= 0) {
+            fd_set readfds, exceptfds;
+            FD_ZERO(&readfds);
+            FD_ZERO(&exceptfds);
+            FD_SET(recv_fd, &readfds);
+            FD_SET(recv_fd, &exceptfds);
+            sr = select(recv_fd+1, &readfds,0,&exceptfds, &timeout);
+        } else {
+            if (timercmp(&timeout, &pollinterval, >))
+                timeout = pollinterval;
+            sr = select(0,0,0,0, &timeout);
+        }
+        if (sr > 0) {
+            recv_fd = -1;
+        } else if (sr == 0) {
+        } else if (sr == -1) {
+            if (errno != EINTR) {
+                fprintf(stderr, "migration child [%ld] exit wait select"
+                        " failed unexpectedly: %s\n",
+                        (long)migration_child, strerror(errno));
+                break;
+            }
+        }
+    }
+}
+
+static void migrate_do_preamble(int send_fd, int recv_fd, pid_t child,
+                                uint8_t *config_data, int config_len,
+                                const char *rune)
+{
+    int rc = 0;
+
+    if (send_fd < 0 || recv_fd < 0) {
+        fprintf(stderr, "migrate_do_preamble: invalid file descriptors\n");
+        exit(EXIT_FAILURE);
+    }
+
+    rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_banner,
+                                   sizeof(migrate_receiver_banner)-1,
+                                   "banner", rune);
+    if (rc) {
+        close(send_fd);
+        migration_child_report(recv_fd);
+        exit(EXIT_FAILURE);
+    }
+
+    save_domain_core_writeconfig(send_fd, "migration stream",
+                                 config_data, config_len);
+
+}
+
+static void migrate_domain(uint32_t domid, const char *rune, int debug,
+                           const char *override_config_file)
+{
+    pid_t child = -1;
+    int rc;
+    int send_fd = -1, recv_fd = -1;
+    char *away_domname;
+    char rc_buf;
+    uint8_t *config_data;
+    int config_len, flags = LIBXL_SUSPEND_LIVE;
+
+    save_domain_core_begin(domid, override_config_file,
+                           &config_data, &config_len);
+
+    if (!config_len) {
+        fprintf(stderr, "No config file stored for running domain and "
+                "none supplied - cannot migrate.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    child = create_migration_child(rune, &send_fd, &recv_fd);
+
+    migrate_do_preamble(send_fd, recv_fd, child, config_data, config_len,
+                        rune);
+
+    xtl_stdiostream_adjust_flags(logger, XTL_STDIOSTREAM_HIDE_PROGRESS, 0);
+
+    if (debug)
+        flags |= LIBXL_SUSPEND_DEBUG;
+    rc = libxl_domain_suspend(ctx, domid, send_fd, flags, NULL);
+    if (rc) {
+        fprintf(stderr, "migration sender: libxl_domain_suspend failed"
+                " (rc=%d)\n", rc);
+        if (rc == ERROR_GUEST_TIMEDOUT)
+            goto failed_suspend;
+        else
+            goto failed_resume;
+    }
+
+    //fprintf(stderr, "migration sender: Transfer complete.\n");
+    // Should only be printed when debugging as it's a bit messy with
+    // progress indication.
+
+    rc = migrate_read_fixedmessage(recv_fd, migrate_receiver_ready,
+                                   sizeof(migrate_receiver_ready),
+                                   "ready message", rune);
+    if (rc) goto failed_resume;
+
+    xtl_stdiostream_adjust_flags(logger, 0, XTL_STDIOSTREAM_HIDE_PROGRESS);
+
+    /* right, at this point we are about give the destination
+     * permission to rename and resume, so we must first rename the
+     * domain away ourselves */
+
+    fprintf(stderr, "migration sender: Target has acknowledged transfer.\n");
+
+    if (common_domname) {
+        xasprintf(&away_domname, "%s--migratedaway", common_domname);
+        rc = libxl_domain_rename(ctx, domid, common_domname, away_domname);
+        if (rc) goto failed_resume;
+    }
+
+    /* point of no return - as soon as we have tried to say
+     * "go" to the receiver, it's not safe to carry on.  We leave
+     * the domain renamed to %s--migratedaway in case that's helpful.
+     */
+
+    fprintf(stderr, "migration sender: Giving target permission to start.\n");
+
+    rc = libxl_write_exactly(ctx, send_fd,
+                             migrate_permission_to_go,
+                             sizeof(migrate_permission_to_go),
+                             "migration stream", "GO message");
+    if (rc) goto failed_badly;
+
+    rc = migrate_read_fixedmessage(recv_fd, migrate_report,
+                                   sizeof(migrate_report),
+                                   "success/failure report message", rune);
+    if (rc) goto failed_badly;
+
+    rc = libxl_read_exactly(ctx, recv_fd,
+                            &rc_buf, 1,
+                            "migration ack stream", "success/failure status");
+    if (rc) goto failed_badly;
+
+    if (rc_buf) {
+        fprintf(stderr, "migration sender: Target reports startup failure"
+                " (status code %d).\n", rc_buf);
+
+        rc = migrate_read_fixedmessage(recv_fd, migrate_permission_to_go,
+                                       sizeof(migrate_permission_to_go),
+                                       "permission for sender to resume",
+                                       rune);
+        if (rc) goto failed_badly;
+
+        fprintf(stderr, "migration sender: Trying to resume at our end.\n");
+
+        if (common_domname) {
+            libxl_domain_rename(ctx, domid, away_domname, common_domname);
+        }
+        rc = libxl_domain_resume(ctx, domid, 1, 0);
+        if (!rc) fprintf(stderr, "migration sender: Resumed OK.\n");
+
+        fprintf(stderr, "Migration failed due to problems at target.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    fprintf(stderr, "migration sender: Target reports successful startup.\n");
+    libxl_domain_destroy(ctx, domid, 0); /* bang! */
+    fprintf(stderr, "Migration successful.\n");
+    exit(EXIT_SUCCESS);
+
+ failed_suspend:
+    close(send_fd);
+    migration_child_report(recv_fd);
+    fprintf(stderr, "Migration failed, failed to suspend at sender.\n");
+    exit(EXIT_FAILURE);
+
+ failed_resume:
+    close(send_fd);
+    migration_child_report(recv_fd);
+    fprintf(stderr, "Migration failed, resuming at sender.\n");
+    libxl_domain_resume(ctx, domid, 1, 0);
+    exit(EXIT_FAILURE);
+
+ failed_badly:
+    fprintf(stderr,
+ "** Migration failed during final handshake **\n"
+ "Domain state is now undefined !\n"
+ "Please CHECK AT BOTH ENDS for running instances, before renaming and\n"
+ " resuming at most one instance.  Two simultaneous instances of the domain\n"
+ " would probably result in SEVERE DATA LOSS and it is now your\n"
+ " responsibility to avoid that.  Sorry.\n");
+
+    close(send_fd);
+    migration_child_report(recv_fd);
+    exit(EXIT_FAILURE);
+}
+
+static void migrate_receive(int debug, int daemonize, int monitor,
+                            int pause_after_migration,
+                            int send_fd, int recv_fd,
+                            libxl_checkpointed_stream checkpointed,
+                            char *colo_proxy_script)
+{
+    uint32_t domid;
+    int rc, rc2;
+    char rc_buf;
+    char *migration_domname;
+    struct domain_create dom_info;
+
+    signal(SIGPIPE, SIG_IGN);
+    /* if we get SIGPIPE we'd rather just have it as an error */
+
+    fprintf(stderr, "migration target: Ready to receive domain.\n");
+
+    CHK_ERRNOVAL(libxl_write_exactly(
+                     ctx, send_fd, migrate_receiver_banner,
+                     sizeof(migrate_receiver_banner)-1,
+                     "migration ack stream", "banner") );
+
+    memset(&dom_info, 0, sizeof(dom_info));
+    dom_info.debug = debug;
+    dom_info.daemonize = daemonize;
+    dom_info.monitor = monitor;
+    dom_info.paused = 1;
+    dom_info.migrate_fd = recv_fd;
+    dom_info.send_back_fd = send_fd;
+    dom_info.migration_domname_r = &migration_domname;
+    dom_info.checkpointed_stream = checkpointed;
+    dom_info.colo_proxy_script = colo_proxy_script;
+
+    rc = create_domain(&dom_info);
+    if (rc < 0) {
+        fprintf(stderr, "migration target: Domain creation failed"
+                " (code %d).\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    domid = rc;
+
+    switch (checkpointed) {
+    case LIBXL_CHECKPOINTED_STREAM_REMUS:
+    case LIBXL_CHECKPOINTED_STREAM_COLO:
+    {
+        const char *ha = checkpointed == LIBXL_CHECKPOINTED_STREAM_COLO ?
+                         "COLO" : "Remus";
+        /* If we are here, it means that the sender (primary) has crashed.
+         * TODO: Split-Brain Check.
+         */
+        fprintf(stderr, "migration target: %s Failover for domain %u\n",
+                ha, domid);
+
+        /*
+         * If domain renaming fails, lets just continue (as we need the domain
+         * to be up & dom names may not matter much, as long as its reachable
+         * over network).
+         *
+         * If domain unpausing fails, destroy domain ? Or is it better to have
+         * a consistent copy of the domain (memory, cpu state, disk)
+         * on atleast one physical host ? Right now, lets just leave the domain
+         * as is and let the Administrator decide (or troubleshoot).
+         */
+        if (migration_domname) {
+            rc = libxl_domain_rename(ctx, domid, migration_domname,
+                                     common_domname);
+            if (rc)
+                fprintf(stderr, "migration target (%s): "
+                        "Failed to rename domain from %s to %s:%d\n",
+                        ha, migration_domname, common_domname, rc);
+        }
+
+        if (checkpointed == LIBXL_CHECKPOINTED_STREAM_COLO)
+            /* The guest is running after failover in COLO mode */
+            exit(rc ? -ERROR_FAIL: 0);
+
+        rc = libxl_domain_unpause(ctx, domid);
+        if (rc)
+            fprintf(stderr, "migration target (%s): "
+                    "Failed to unpause domain %s (id: %u):%d\n",
+                    ha, common_domname, domid, rc);
+
+        exit(rc ? EXIT_FAILURE : EXIT_SUCCESS);
+    }
+    default:
+        /* do nothing */
+        break;
+    }
+
+    fprintf(stderr, "migration target: Transfer complete,"
+            " requesting permission to start domain.\n");
+
+    rc = libxl_write_exactly(ctx, send_fd,
+                             migrate_receiver_ready,
+                             sizeof(migrate_receiver_ready),
+                             "migration ack stream", "ready message");
+    if (rc) exit(EXIT_FAILURE);
+
+    rc = migrate_read_fixedmessage(recv_fd, migrate_permission_to_go,
+                                   sizeof(migrate_permission_to_go),
+                                   "GO message", 0);
+    if (rc) goto perhaps_destroy_notify_rc;
+
+    fprintf(stderr, "migration target: Got permission, starting domain.\n");
+
+    if (migration_domname) {
+        rc = libxl_domain_rename(ctx, domid, migration_domname, common_domname);
+        if (rc) goto perhaps_destroy_notify_rc;
+    }
+
+    if (!pause_after_migration) {
+        rc = libxl_domain_unpause(ctx, domid);
+        if (rc) goto perhaps_destroy_notify_rc;
+    }
+
+    fprintf(stderr, "migration target: Domain started successsfully.\n");
+    rc = 0;
+
+ perhaps_destroy_notify_rc:
+    rc2 = libxl_write_exactly(ctx, send_fd,
+                              migrate_report, sizeof(migrate_report),
+                              "migration ack stream",
+                              "success/failure report");
+    if (rc2) exit(EXIT_FAILURE);
+
+    rc_buf = -rc;
+    assert(!!rc_buf == !!rc);
+    rc2 = libxl_write_exactly(ctx, send_fd, &rc_buf, 1,
+                              "migration ack stream",
+                              "success/failure code");
+    if (rc2) exit(EXIT_FAILURE);
+
+    if (rc) {
+        fprintf(stderr, "migration target: Failure, destroying our copy.\n");
+
+        rc2 = libxl_domain_destroy(ctx, domid, 0);
+        if (rc2) {
+            fprintf(stderr, "migration target: Failed to destroy our copy"
+                    " (code %d).\n", rc2);
+            exit(EXIT_FAILURE);
+        }
+
+        fprintf(stderr, "migration target: Cleanup OK, granting sender"
+                " permission to resume.\n");
+
+        rc2 = libxl_write_exactly(ctx, send_fd,
+                                  migrate_permission_to_go,
+                                  sizeof(migrate_permission_to_go),
+                                  "migration ack stream",
+                                  "permission to sender to have domain back");
+        if (rc2) exit(EXIT_FAILURE);
+    }
+
+    exit(EXIT_SUCCESS);
+}
+
+
+int main_migrate_receive(int argc, char **argv)
+{
+    int debug = 0, daemonize = 1, monitor = 1, pause_after_migration = 0;
+    libxl_checkpointed_stream checkpointed = LIBXL_CHECKPOINTED_STREAM_NONE;
+    int opt;
+    char *script = NULL;
+    static struct option opts[] = {
+        {"colo", 0, 0, 0x100},
+        /* It is a shame that the management code for disk is not here. */
+        {"coloft-script", 1, 0, 0x200},
+        COMMON_LONG_OPTS
+    };
+
+    SWITCH_FOREACH_OPT(opt, "Fedrp", opts, "migrate-receive", 0) {
+    case 'F':
+        daemonize = 0;
+        break;
+    case 'e':
+        daemonize = 0;
+        monitor = 0;
+        break;
+    case 'd':
+        debug = 1;
+        break;
+    case 'r':
+        checkpointed = LIBXL_CHECKPOINTED_STREAM_REMUS;
+        break;
+    case 0x100:
+        checkpointed = LIBXL_CHECKPOINTED_STREAM_COLO;
+        break;
+    case 0x200:
+        script = optarg;
+        break;
+    case 'p':
+        pause_after_migration = 1;
+        break;
+    }
+
+    if (argc-optind != 0) {
+        help("migrate-receive");
+        return EXIT_FAILURE;
+    }
+    migrate_receive(debug, daemonize, monitor, pause_after_migration,
+                    STDOUT_FILENO, STDIN_FILENO,
+                    checkpointed, script);
+
+    return EXIT_SUCCESS;
+}
+
+int main_migrate(int argc, char **argv)
+{
+    uint32_t domid;
+    const char *config_filename = NULL;
+    const char *ssh_command = "ssh";
+    char *rune = NULL;
+    char *host;
+    int opt, daemonize = 1, monitor = 1, debug = 0, pause_after_migration = 0;
+    static struct option opts[] = {
+        {"debug", 0, 0, 0x100},
+        {"live", 0, 0, 0x200},
+        COMMON_LONG_OPTS
+    };
+
+    SWITCH_FOREACH_OPT(opt, "FC:s:ep", opts, "migrate", 2) {
+    case 'C':
+        config_filename = optarg;
+        break;
+    case 's':
+        ssh_command = optarg;
+        break;
+    case 'F':
+        daemonize = 0;
+        break;
+    case 'e':
+        daemonize = 0;
+        monitor = 0;
+        break;
+    case 'p':
+        pause_after_migration = 1;
+        break;
+    case 0x100: /* --debug */
+        debug = 1;
+        break;
+    case 0x200: /* --live */
+        /* ignored for compatibility with xm */
+        break;
+    }
+
+    domid = xfind_domain(argv[optind]);
+    host = argv[optind + 1];
+
+    bool pass_tty_arg = progress_use_cr || (isatty(2) > 0);
+
+    if (!ssh_command[0]) {
+        rune= host;
+    } else {
+        char verbose_buf[minmsglevel_default+3];
+        int verbose_len;
+        verbose_buf[0] = ' ';
+        verbose_buf[1] = '-';
+        memset(verbose_buf+2, 'v', minmsglevel_default);
+        verbose_buf[sizeof(verbose_buf)-1] = 0;
+        if (minmsglevel == minmsglevel_default) {
+            verbose_len = 0;
+        } else {
+            verbose_len = (minmsglevel_default - minmsglevel) + 2;
+        }
+        xasprintf(&rune, "exec %s %s xl%s%.*s migrate-receive%s%s%s",
+                  ssh_command, host,
+                  pass_tty_arg ? " -t" : "",
+                  verbose_len, verbose_buf,
+                  daemonize ? "" : " -e",
+                  debug ? " -d" : "",
+                  pause_after_migration ? " -p" : "");
+    }
+
+    migrate_domain(domid, rune, debug, config_filename);
+    return EXIT_SUCCESS;
+}
+
+int main_remus(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, rc, daemonize = 1;
+    const char *ssh_command = "ssh";
+    char *host = NULL, *rune = NULL;
+    libxl_domain_remus_info r_info;
+    int send_fd = -1, recv_fd = -1;
+    pid_t child = -1;
+    uint8_t *config_data;
+    int config_len;
+
+    memset(&r_info, 0, sizeof(libxl_domain_remus_info));
+
+    SWITCH_FOREACH_OPT(opt, "Fbundi:s:N:ec", NULL, "remus", 2) {
+    case 'i':
+        r_info.interval = atoi(optarg);
+        break;
+    case 'F':
+        libxl_defbool_set(&r_info.allow_unsafe, true);
+        break;
+    case 'b':
+        libxl_defbool_set(&r_info.blackhole, true);
+        break;
+    case 'u':
+        libxl_defbool_set(&r_info.compression, false);
+        break;
+    case 'n':
+        libxl_defbool_set(&r_info.netbuf, false);
+        break;
+    case 'N':
+        r_info.netbufscript = optarg;
+        break;
+    case 'd':
+        libxl_defbool_set(&r_info.diskbuf, false);
+        break;
+    case 's':
+        ssh_command = optarg;
+        break;
+    case 'e':
+        daemonize = 0;
+        break;
+    case 'c':
+        libxl_defbool_set(&r_info.colo, true);
+    }
+
+    domid = xfind_domain(argv[optind]);
+    host = argv[optind + 1];
+
+    /* Defaults */
+    libxl_defbool_setdefault(&r_info.blackhole, false);
+    libxl_defbool_setdefault(&r_info.colo, false);
+    if (!libxl_defbool_val(r_info.colo) && !r_info.interval)
+        r_info.interval = 200;
+
+    if (libxl_defbool_val(r_info.colo)) {
+        if (r_info.interval || libxl_defbool_val(r_info.blackhole) ||
+            !libxl_defbool_is_default(r_info.netbuf) ||
+            !libxl_defbool_is_default(r_info.diskbuf)) {
+            perror("option -c is conflict with -i, -d, -n or -b");
+            exit(-1);
+        }
+
+        if (libxl_defbool_is_default(r_info.compression)) {
+            perror("COLO can't be used with memory compression. "
+                   "Disable memory checkpoint compression now...");
+            libxl_defbool_set(&r_info.compression, false);
+        }
+    }
+
+    if (!r_info.netbufscript) {
+        if (libxl_defbool_val(r_info.colo))
+            r_info.netbufscript = default_colo_proxy_script;
+        else
+            r_info.netbufscript = default_remus_netbufscript;
+    }
+
+    if (libxl_defbool_val(r_info.blackhole)) {
+        send_fd = open("/dev/null", O_RDWR, 0644);
+        if (send_fd < 0) {
+            perror("failed to open /dev/null");
+            exit(EXIT_FAILURE);
+        }
+    } else {
+
+        if (!ssh_command[0]) {
+            rune = host;
+        } else {
+            if (!libxl_defbool_val(r_info.colo)) {
+                xasprintf(&rune, "exec %s %s xl migrate-receive %s %s",
+                          ssh_command, host,
+                          "-r",
+                          daemonize ? "" : " -e");
+            } else {
+                xasprintf(&rune, "exec %s %s xl migrate-receive %s %s %s %s",
+                          ssh_command, host,
+                          "--colo",
+                          r_info.netbufscript ? "--coloft-script" : "",
+                          r_info.netbufscript ? r_info.netbufscript : "",
+                          daemonize ? "" : " -e");
+            }
+        }
+
+        save_domain_core_begin(domid, NULL, &config_data, &config_len);
+
+        if (!config_len) {
+            fprintf(stderr, "No config file stored for running domain and "
+                    "none supplied - cannot start remus.\n");
+            exit(EXIT_FAILURE);
+        }
+
+        child = create_migration_child(rune, &send_fd, &recv_fd);
+
+        migrate_do_preamble(send_fd, recv_fd, child, config_data, config_len,
+                            rune);
+
+        if (ssh_command[0])
+            free(rune);
+    }
+
+    /* Point of no return */
+    rc = libxl_domain_remus_start(ctx, &r_info, domid, send_fd, recv_fd, 0);
+
+    /* check if the domain exists. User may have xl destroyed the
+     * domain to force failover
+     */
+    if (libxl_domain_info(ctx, 0, domid)) {
+        fprintf(stderr, "%s: Primary domain has been destroyed.\n",
+                libxl_defbool_val(r_info.colo) ? "COLO" : "Remus");
+        close(send_fd);
+        return EXIT_SUCCESS;
+    }
+
+    /* If we are here, it means remus setup/domain suspend/backup has
+     * failed. Try to resume the domain and exit gracefully.
+     * TODO: Split-Brain check.
+     */
+    if (rc == ERROR_GUEST_TIMEDOUT)
+        fprintf(stderr, "Failed to suspend domain at primary.\n");
+    else {
+        fprintf(stderr, "%s: Backup failed? resuming domain at primary.\n",
+                libxl_defbool_val(r_info.colo) ? "COLO" : "Remus");
+        libxl_domain_resume(ctx, domid, 1, 0);
+    }
+
+    close(send_fd);
+    return EXIT_FAILURE;
+}
+#endif
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 29/29] xl: merge xl_cmdimpl.c into xl.c
  2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
                   ` (27 preceding siblings ...)
  2017-02-24 16:13 ` [PATCH 28/29] xl: split out migration " Wei Liu
@ 2017-02-24 16:13 ` Wei Liu
  2017-02-27 15:58   ` Ian Jackson
  28 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-24 16:13 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

After splitting out all the meaty bits, xl_cmdimpl.c doesn't contain
much. Merge the rest into xl.c and delete the file.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   2 +-
 tools/xl/xl.c         |  58 +++++++++++++++++++++++++++
 tools/xl/xl_cmdimpl.c | 107 --------------------------------------------------
 3 files changed, 59 insertions(+), 108 deletions(-)
 delete mode 100644 tools/xl/xl_cmdimpl.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index 8c30fdcf9e..7b73e1b574 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -15,7 +15,7 @@ LDFLAGS += $(PTHREAD_LDFLAGS)
 CFLAGS_XL += $(CFLAGS_libxenlight)
 CFLAGS_XL += -Wshadow
 
-XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
+XL_OBJS = xl.o xl_cmdtable.o xl_sxp.o xl_utils.o
 XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
 XL_OBJS += xl_vtpm.o xl_block.o xl_nic.o xl_usb.o
 XL_OBJS += xl_sched.o xl_pci.o xl_vcpu.o xl_cd.o xl_mem.o
diff --git a/tools/xl/xl.c b/tools/xl/xl.c
index 32346ad7a5..02179a6229 100644
--- a/tools/xl/xl.c
+++ b/tools/xl/xl.c
@@ -48,6 +48,15 @@ bool progress_use_cr = 0;
 
 xentoollog_level minmsglevel = minmsglevel_default;
 
+int logfile = 2;
+
+/* every libxl action in xl uses this same libxl context */
+libxl_ctx *ctx;
+
+xlchild children[child_max];
+
+const char *common_domname;
+
 /* Get autoballoon option based on presence of dom0_mem Xen command
    line option. */
 static int auto_autoballoon(void)
@@ -370,6 +379,55 @@ int main(int argc, char **argv)
     return ret;
 }
 
+int child_report(xlchildnum child)
+{
+    int status;
+    pid_t got = xl_waitpid(child, &status, 0);
+    if (got < 0) {
+        fprintf(stderr, "xl: warning, failed to waitpid for %s: %s\n",
+                children[child].description, strerror(errno));
+        return ERROR_FAIL;
+    } else if (status) {
+        xl_report_child_exitstatus(XTL_ERROR, child, got, status);
+        return ERROR_FAIL;
+    } else {
+        return 0;
+    }
+}
+
+void help(const char *command)
+{
+    int i;
+    struct cmd_spec *cmd;
+
+    if (!command || !strcmp(command, "help")) {
+        printf("Usage xl [-vfN] <subcommand> [args]\n\n");
+        printf("xl full list of subcommands:\n\n");
+        for (i = 0; i < cmdtable_len; i++) {
+            printf(" %-19s ", cmd_table[i].cmd_name);
+            if (strlen(cmd_table[i].cmd_name) > 19)
+                printf("\n %-19s ", "");
+            printf("%s\n", cmd_table[i].cmd_desc);
+        }
+    } else {
+        cmd = cmdtable_lookup(command);
+        if (cmd) {
+            printf("Usage: xl [-v%s%s] %s %s\n\n%s.\n\n",
+                   cmd->modifies ? "f" : "",
+                   cmd->can_dryrun ? "N" : "",
+                   cmd->cmd_name,
+                   cmd->cmd_usage,
+                   cmd->cmd_desc);
+            if (cmd->cmd_option)
+                printf("Options:\n\n%s\n", cmd->cmd_option);
+        }
+        else {
+            printf("command \"%s\" not implemented\n", command);
+        }
+    }
+}
+
+
 /*
  * Local variables:
  * mode: C
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
deleted file mode 100644
index bd7f8edb0a..0000000000
--- a/tools/xl/xl_cmdimpl.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright 2009-2017 Citrix Ltd and other contributors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; version 2.1 only. with the special
- * exception on linking described in file LICENSE.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- */
-
-#define _GNU_SOURCE
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <sys/utsname.h> /* for utsname in xl info */
-#include <xentoollog.h>
-#include <ctype.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <xen/hvm/e820.h>
-
-#include <libxl.h>
-#include <libxl_utils.h>
-#include <libxl_json.h>
-#include <libxlutil.h>
-#include "xl.h"
-#include "xl_utils.h"
-#include "xl_parse.h"
-
-int logfile = 2;
-
-/* every libxl action in xl uses this same libxl context */
-libxl_ctx *ctx;
-
-xlchild children[child_max];
-
-const char *common_domname;
-
-int child_report(xlchildnum child)
-{
-    int status;
-    pid_t got = xl_waitpid(child, &status, 0);
-    if (got < 0) {
-        fprintf(stderr, "xl: warning, failed to waitpid for %s: %s\n",
-                children[child].description, strerror(errno));
-        return ERROR_FAIL;
-    } else if (status) {
-        xl_report_child_exitstatus(XTL_ERROR, child, got, status);
-        return ERROR_FAIL;
-    } else {
-        return 0;
-    }
-}
-
-void help(const char *command)
-{
-    int i;
-    struct cmd_spec *cmd;
-
-    if (!command || !strcmp(command, "help")) {
-        printf("Usage xl [-vfN] <subcommand> [args]\n\n");
-        printf("xl full list of subcommands:\n\n");
-        for (i = 0; i < cmdtable_len; i++) {
-            printf(" %-19s ", cmd_table[i].cmd_name);
-            if (strlen(cmd_table[i].cmd_name) > 19)
-                printf("\n %-19s ", "");
-            printf("%s\n", cmd_table[i].cmd_desc);
-        }
-    } else {
-        cmd = cmdtable_lookup(command);
-        if (cmd) {
-            printf("Usage: xl [-v%s%s] %s %s\n\n%s.\n\n",
-                   cmd->modifies ? "f" : "",
-                   cmd->can_dryrun ? "N" : "",
-                   cmd->cmd_name,
-                   cmd->cmd_usage,
-                   cmd->cmd_desc);
-            if (cmd->cmd_option)
-                printf("Options:\n\n%s\n", cmd->cmd_option);
-        }
-        else {
-            printf("command \"%s\" not implemented\n", command);
-        }
-    }
-}
-
-/*
- * Local variables:
- * mode: C
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* Re: [PATCH 08/29] xl: move some helper functions to xl_utils.c
  2017-02-24 16:12 ` [PATCH 08/29] xl: move some helper functions to xl_utils.c Wei Liu
@ 2017-02-27 15:53   ` Ian Jackson
  2017-02-27 17:44     ` [PATCH] " Wei Liu
  0 siblings, 1 reply; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:53 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 08/29] xl: move some helper functions to xl_utils.c"):
> Move some commonly used functions to a new file. Prepend "x" to
> function names to stick to consistent naming scheme.

The `xfoo' naming scheme is a reference to `xmalloc' et al, which
conventionally crash the program on failure.

I don't think you need to add this to every function in xl.  It is
applicable only when there is an existing function which returns an
error code, which is wrapped by one which never fails.

Thanks,
Ian.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 01/29] xl: remove accidentally committed hunk from Makefile
  2017-02-24 16:12 ` [PATCH 01/29] xl: remove accidentally committed hunk from Makefile Wei Liu
@ 2017-02-27 15:53   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:53 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 01/29] xl: remove accidentally committed hunk from Makefile"):
> It was never intended to be committed. Lucky the high level Makefile was
> correct so it didn't cause us problem when building xl.

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 03/29] xl: remove inclusion of libxl_osdeps.h
  2017-02-24 16:12 ` [PATCH 03/29] xl: remove inclusion of libxl_osdeps.h Wei Liu
@ 2017-02-27 15:53   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:53 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 03/29] xl: remove inclusion of libxl_osdeps.h"):
> There is no reason for a client to include a private header from libxl.
> Remove the inclusion and define _GNU_SOURCE for {v,}asprintf in
> xl_cmdimpl.c.

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 02/29] xl: update copyright information
  2017-02-24 16:12 ` [PATCH 02/29] xl: update copyright information Wei Liu
@ 2017-02-27 15:54   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:54 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 02/29] xl: update copyright information"):
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 05/29] xl: generate _paths.h
  2017-02-24 16:12 ` [PATCH 05/29] xl: generate _paths.h Wei Liu
@ 2017-02-27 15:54   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:54 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 05/29] xl: generate _paths.h"):
> It is included by xl.h. Previously it was using _paths.h from some other
> place. We'd better generate one for xl as well.

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 04/29] xl: use <> variant to include Xen tools library headers
  2017-02-24 16:12 ` [PATCH 04/29] xl: use <> variant to include Xen tools library headers Wei Liu
@ 2017-02-27 15:54   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:54 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 04/29] xl: use <> variant to include Xen tools library headers"):
> They should be treated like any other libraries installed on the build
> host. Compiler options are set correctly to point to their locations.

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 06/29] xl: remove trailing spaces in xl_cmdimpl.c
  2017-02-24 16:12 ` [PATCH 06/29] xl: remove trailing spaces in xl_cmdimpl.c Wei Liu
@ 2017-02-27 15:54   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:54 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 06/29] xl: remove trailing spaces in xl_cmdimpl.c"):
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 07/29] xl: lift a bunch of macros to xl_utils.h
  2017-02-24 16:12 ` [PATCH 07/29] xl: lift a bunch of macros to xl_utils.h Wei Liu
@ 2017-02-27 15:54   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:54 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 07/29] xl: lift a bunch of macros to xl_utils.h"):
> We're going to split xl_cmdimpl.c into multiple files. Lift the commonly
> used macros to xl_utils.h.

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 09/29] xl: split out tmem related code to xl_tmem.c
  2017-02-24 16:12 ` [PATCH 09/29] xl: split out tmem related code to xl_tmem.c Wei Liu
@ 2017-02-27 15:54   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:54 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 09/29] xl: split out tmem related code to xl_tmem.c"):
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 13/29] xl: split out vtpm related code
  2017-02-24 16:12 ` [PATCH 13/29] xl: split out vtpm " Wei Liu
@ 2017-02-27 15:55   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:55 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 13/29] xl: split out vtpm related code"):
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 22/29] xl: split out psr related code
  2017-02-24 16:13 ` [PATCH 22/29] xl: split out psr " Wei Liu
@ 2017-02-27 15:55   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:55 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 22/29] xl: split out psr related code"):
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 20/29] xl: split out cd related code
  2017-02-24 16:13 ` [PATCH 20/29] xl: split out cd " Wei Liu
@ 2017-02-27 15:56   ` Ian Jackson
  2017-02-27 16:23     ` Wei Liu
  0 siblings, 1 reply; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:56 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 20/29] xl: split out cd related code"):
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>
> ---
>  tools/xl/Makefile     |   2 +-
>  tools/xl/xl_cd.c      | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++

Would you mind calling this `libxl_cdrom.c' rather than `_cd' ?
The latter makes me think of chdir...

Thanks,
Ian.


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 10/29] xl: split out xl_parse.[ch]
  2017-02-24 16:12 ` [PATCH 10/29] xl: split out xl_parse.[ch] Wei Liu
@ 2017-02-27 15:57   ` Ian Jackson
  2017-02-27 17:47     ` [PATCH 1/3] xl: rename cpurange_parse to parse_cpurange Wei Liu
  0 siblings, 1 reply; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:57 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 10/29] xl: split out xl_parse.[ch]"):
> Some notable changes other than code movement:
> 1. rename cpurange_parse to parse_cpurange;
> 2. provide a function to return shutdown action name.

Can you split that out so that I can review it separately from the
code motion ?

Thanks,
Ian.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 17/29] xl: split out scheduler related code
  2017-02-24 16:13 ` [PATCH 17/29] xl: split out scheduler " Wei Liu
@ 2017-02-27 15:57   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:57 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 17/29] xl: split out scheduler related code"):
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

BTW, for all of these code motion patches: it would be nice if the
comment said `code motion only, apart from the obvious Makefile
change' or something.

Ian.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 25/29] xl: split out miscellaneous functions
  2017-02-24 16:13 ` [PATCH 25/29] xl: split out miscellaneous functions Wei Liu
@ 2017-02-27 15:58   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:58 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 25/29] xl: split out miscellaneous functions"):
> A collections of functions that don't warrant their own files.
> 
> Moving main_devd there requires lifting do_daemonize to xl_utils.c.

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 29/29] xl: merge xl_cmdimpl.c into xl.c
  2017-02-24 16:13 ` [PATCH 29/29] xl: merge xl_cmdimpl.c into xl.c Wei Liu
@ 2017-02-27 15:58   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:58 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 29/29] xl: merge xl_cmdimpl.c into xl.c"):
> After splitting out all the meaty bits, xl_cmdimpl.c doesn't contain
> much. Merge the rest into xl.c and delete the file.

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 14/29] xl: split out block related code
  2017-02-24 16:12 ` [PATCH 14/29] xl: split out block " Wei Liu
@ 2017-02-27 15:58   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:58 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 14/29] xl: split out block related code"):
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 24/29] xl: split out vnc and console related code
  2017-02-24 16:13 ` [PATCH 24/29] xl: split out vnc and console related code Wei Liu
@ 2017-02-27 15:59   ` Ian Jackson
  2017-02-27 17:48     ` [PATCH 1/2] xl: call libxl_vncviewer_exec in main_vncviewer Wei Liu
  0 siblings, 1 reply; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:59 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 24/29] xl: split out vnc and console related code"):
> The new file also contains code for channel, which is just a console
> in disguise.
> 
> Replace the call to vncviewer() with libxl_vncviewer_exec() directly in
> main_vncviewer.

Again, please separate out the non-code-motion change.

Thanks,
Ian.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 19/29] xl: split out vcpu related code
  2017-02-24 16:13 ` [PATCH 19/29] xl: split out vcpu " Wei Liu
@ 2017-02-27 15:59   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:59 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 19/29] xl: split out vcpu related code"):
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 28/29] xl: split out migration related code
  2017-02-24 16:13 ` [PATCH 28/29] xl: split out migration " Wei Liu
@ 2017-02-27 15:59   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:59 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 28/29] xl: split out migration related code"):
> Include COLO / Remus code because they are built on top of the existing
> migration protocol.

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 11/29] xl: split out cpupool related code
  2017-02-24 16:12 ` [PATCH 11/29] xl: split out cpupool related code Wei Liu
@ 2017-02-27 15:59   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 15:59 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 11/29] xl: split out cpupool related code"):
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 26/29] xl: split out vm lifecycle control functions
  2017-02-24 16:13 ` [PATCH 26/29] xl: split out vm lifecycle control functions Wei Liu
@ 2017-02-27 16:00   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 16:00 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 26/29] xl: split out vm lifecycle control functions"):
> Including create, reboot, shutdown, pause, unpause and destroy.
> 
> Lift a bunch of core data structures and function declarations to xl.h
> because they are needed in both xl_cmdimpl.c and xl_vmcontrol.c.

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 16/29] xl: split out usb related code
  2017-02-24 16:13 ` [PATCH 16/29] xl: split out usb " Wei Liu
@ 2017-02-27 16:00   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 16:00 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 16/29] xl: split out usb related code"):
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 23/29] xl: split out functions to print out information
  2017-02-24 16:13 ` [PATCH 23/29] xl: split out functions to print out information Wei Liu
@ 2017-02-27 16:00   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 16:00 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 23/29] xl: split out functions to print out information"):
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 15/29] xl: split out network related code
  2017-02-24 16:13 ` [PATCH 15/29] xl: split out network " Wei Liu
@ 2017-02-27 16:01   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 16:01 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 15/29] xl: split out network related code"):
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 21/29] xl: split out memory related code
  2017-02-24 16:13 ` [PATCH 21/29] xl: split out memory " Wei Liu
@ 2017-02-27 16:01   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 16:01 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 21/29] xl: split out memory related code"):
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 12/29] xl: split out flask related code
  2017-02-24 16:12 ` [PATCH 12/29] xl: split out flask " Wei Liu
@ 2017-02-27 16:01   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 16:01 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 12/29] xl: split out flask related code"):
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 27/29] xl: split out save/restore related code
  2017-02-24 16:13 ` [PATCH 27/29] xl: split out save/restore related code Wei Liu
@ 2017-02-27 16:01   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 16:01 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 27/29] xl: split out save/restore related code"):
> Add some function declarations to xl.h because they are now needed in
> multiple files.

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 18/29] xl: split out pci related code
  2017-02-24 16:13 ` [PATCH 18/29] xl: split out pci " Wei Liu
@ 2017-02-27 16:01   ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 16:01 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 18/29] xl: split out pci related code"):
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 20/29] xl: split out cd related code
  2017-02-27 15:56   ` Ian Jackson
@ 2017-02-27 16:23     ` Wei Liu
  2017-02-27 16:36       ` Ian Jackson
  0 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-27 16:23 UTC (permalink / raw)
  To: Ian Jackson; +Cc: Xen-devel, Wei Liu

On Mon, Feb 27, 2017 at 03:56:21PM +0000, Ian Jackson wrote:
> Wei Liu writes ("[PATCH 20/29] xl: split out cd related code"):
> > Signed-off-by: Wei Liu <wei.liu2@citrix.com>
> > ---
> >  tools/xl/Makefile     |   2 +-
> >  tools/xl/xl_cd.c      | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++
> 
> Would you mind calling this `libxl_cdrom.c' rather than `_cd' ?
> The latter makes me think of chdir...

Can I have your ack if I rename it to libxl_cdrom.c?

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 20/29] xl: split out cd related code
  2017-02-27 16:23     ` Wei Liu
@ 2017-02-27 16:36       ` Ian Jackson
  2017-02-27 16:38         ` Wei Liu
  0 siblings, 1 reply; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 16:36 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("Re: [PATCH 20/29] xl: split out cd related code"):
> On Mon, Feb 27, 2017 at 03:56:21PM +0000, Ian Jackson wrote:
> > Wei Liu writes ("[PATCH 20/29] xl: split out cd related code"):
> > > Signed-off-by: Wei Liu <wei.liu2@citrix.com>
> > > ---
> > >  tools/xl/Makefile     |   2 +-
> > >  tools/xl/xl_cd.c      | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++
> > 
> > Would you mind calling this `libxl_cdrom.c' rather than `_cd' ?
> > The latter makes me think of chdir...
> 
> Can I have your ack if I rename it to libxl_cdrom.c?

Yes, indeed, that was the only reason I didn't ack it.

Thanks,
Ian.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 20/29] xl: split out cd related code
  2017-02-27 16:36       ` Ian Jackson
@ 2017-02-27 16:38         ` Wei Liu
  2017-02-27 16:44           ` Ian Jackson
  0 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-27 16:38 UTC (permalink / raw)
  To: Ian Jackson; +Cc: Xen-devel, Wei Liu

On Mon, Feb 27, 2017 at 04:36:16PM +0000, Ian Jackson wrote:
> Wei Liu writes ("Re: [PATCH 20/29] xl: split out cd related code"):
> > On Mon, Feb 27, 2017 at 03:56:21PM +0000, Ian Jackson wrote:
> > > Wei Liu writes ("[PATCH 20/29] xl: split out cd related code"):
> > > > Signed-off-by: Wei Liu <wei.liu2@citrix.com>
> > > > ---
> > > >  tools/xl/Makefile     |   2 +-
> > > >  tools/xl/xl_cd.c      | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++
> > > 
> > > Would you mind calling this `libxl_cdrom.c' rather than `_cd' ?
> > > The latter makes me think of chdir...
> > 
> > Can I have your ack if I rename it to libxl_cdrom.c?
> 
> Yes, indeed, that was the only reason I didn't ack it.

Thanks.  I want to avoid reposting as much as possible because this
series is really long and tedious.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 20/29] xl: split out cd related code
  2017-02-27 16:38         ` Wei Liu
@ 2017-02-27 16:44           ` Ian Jackson
  2017-02-27 16:45             ` Wei Liu
  0 siblings, 1 reply; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 16:44 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("Re: [PATCH 20/29] xl: split out cd related code"):
> On Mon, Feb 27, 2017 at 04:36:16PM +0000, Ian Jackson wrote:
> > Yes, indeed, that was the only reason I didn't ack it.
> 
> Thanks.  I want to avoid reposting as much as possible because this
> series is really long and tedious.

Indeed!

There were about three other patches that I had small comments on.  If
you want to repost just those, that would be fine by me.

Ian.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 20/29] xl: split out cd related code
  2017-02-27 16:44           ` Ian Jackson
@ 2017-02-27 16:45             ` Wei Liu
  0 siblings, 0 replies; 76+ messages in thread
From: Wei Liu @ 2017-02-27 16:45 UTC (permalink / raw)
  To: Ian Jackson; +Cc: Xen-devel, Wei Liu

On Mon, Feb 27, 2017 at 04:44:53PM +0000, Ian Jackson wrote:
> Wei Liu writes ("Re: [PATCH 20/29] xl: split out cd related code"):
> > On Mon, Feb 27, 2017 at 04:36:16PM +0000, Ian Jackson wrote:
> > > Yes, indeed, that was the only reason I didn't ack it.
> > 
> > Thanks.  I want to avoid reposting as much as possible because this
> > series is really long and tedious.
> 
> Indeed!
> 
> There were about three other patches that I had small comments on.  If
> you want to repost just those, that would be fine by me.
> 

Sure.

> Ian.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [PATCH] xl: move some helper functions to xl_utils.c
  2017-02-27 15:53   ` Ian Jackson
@ 2017-02-27 17:44     ` Wei Liu
  2017-02-28 10:32       ` Ian Jackson
  0 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-27 17:44 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Move some commonly used functions to a new file.

find_domain requires access to global variable common_domname. Make that
non-static.

No functional change.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   2 +-
 tools/xl/xl_cmdimpl.c | 221 +-----------------------------------------
 tools/xl/xl_utils.c   | 258 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/xl/xl_utils.h   |  27 ++++++
 4 files changed, 287 insertions(+), 221 deletions(-)
 create mode 100644 tools/xl/xl_utils.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index 7106009d66..2f740b4789 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -15,7 +15,7 @@ LDFLAGS += $(PTHREAD_LDFLAGS)
 CFLAGS_XL += $(CFLAGS_libxenlight)
 CFLAGS_XL += -Wshadow
 
-XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o
+XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
 $(XL_OBJS): CFLAGS += -include $(XEN_ROOT)/tools/config.h # libxl_json.h needs it.
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index d9d947827d..de9e6add65 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -19,7 +19,6 @@
 #include <string.h>
 #include <unistd.h>
 #include <time.h>
-#include <getopt.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/time.h>
@@ -48,7 +47,7 @@ libxl_ctx *ctx;
 
 xlchild children[child_max];
 
-static const char *common_domname;
+const char *common_domname;
 static int fd_lock = -1;
 
 static const char savefileheader_magic[32]=
@@ -129,22 +128,6 @@ struct domain_create {
     char **migration_domname_r; /* from malloc */
 };
 
-
-static uint32_t find_domain(const char *p) __attribute__((warn_unused_result));
-static uint32_t find_domain(const char *p)
-{
-    uint32_t domid;
-    int rc;
-
-    rc = libxl_domain_qualifier_to_domid(ctx, p, &domid);
-    if (rc) {
-        fprintf(stderr, "%s is an invalid domain identifier (rc=%d)\n", p, rc);
-        exit(EXIT_FAILURE);
-    }
-    common_domname = libxl_domid_to_name(ctx, domid);
-    return domid;
-}
-
 int child_report(xlchildnum child)
 {
     int status;
@@ -253,47 +236,6 @@ release_lock:
     return rc;
 }
 
-static void *xmalloc(size_t sz) {
-    void *r;
-    r = malloc(sz);
-    if (!r) { fprintf(stderr,"xl: Unable to malloc %lu bytes.\n",
-                      (unsigned long)sz); exit(-ERROR_FAIL); }
-    return r;
-}
-
-static void *xcalloc(size_t n, size_t sz) __attribute__((unused));
-static void *xcalloc(size_t n, size_t sz) {
-    void *r = calloc(n, sz);
-    if (!r) {
-        fprintf(stderr,"xl: Unable to calloc %zu bytes.\n", sz*n);
-        exit(-ERROR_FAIL);
-    }
-    return r;
-}
-
-static void *xrealloc(void *ptr, size_t sz) {
-    void *r;
-    if (!sz) { free(ptr); return 0; }
-      /* realloc(non-0, 0) has a useless return value;
-       * but xrealloc(anything, 0) is like free
-       */
-    r = realloc(ptr, sz);
-    if (!r) { fprintf(stderr,"xl: Unable to realloc to %lu bytes.\n",
-                      (unsigned long)sz); exit(-ERROR_FAIL); }
-    return r;
-}
-
-static char *xstrdup(const char *x)
-{
-    char *r;
-    r = strdup(x);
-    if (!r) {
-        fprintf(stderr, "xl: Unable to strdup a string of length %zu.\n",
-                strlen(x));
-        exit(-ERROR_FAIL);
-    }
-    return r;
-}
 
 #define ARRAY_EXTEND_INIT__CORE(array,count,initfn,more)                \
     ({                                                                  \
@@ -313,46 +255,6 @@ static char *xstrdup(const char *x)
 #define ARRAY_EXTEND_INIT_NODEVID(array,count,initfn) \
     ARRAY_EXTEND_INIT__CORE((array),(count),(initfn), /* nothing */ )
 
-static void dolog(const char *file, int line, const char *func, char *fmt, ...)
-     __attribute__((format(printf,4,5)));
-
-static void dolog(const char *file, int line, const char *func, char *fmt, ...)
-{
-    va_list ap;
-    char *s = NULL;
-    int rc;
-
-    va_start(ap, fmt);
-    rc = vasprintf(&s, fmt, ap);
-    va_end(ap);
-    if (rc >= 0)
-        /* we ignore write errors since we have no way to report them;
-         * the alternative would be to abort the whole program */
-        libxl_write_exactly(NULL, logfile, s, rc, NULL, NULL);
-    free(s);
-}
-
-static void xvasprintf(char **strp, const char *fmt, va_list ap)
-    __attribute__((format(printf,2,0)));
-static void xvasprintf(char **strp, const char *fmt, va_list ap)
-{
-    int r = vasprintf(strp, fmt, ap);
-    if (r == -1) {
-        perror("asprintf failed");
-        exit(EXIT_FAILURE);
-    }
-}
-
-static void xasprintf(char **strp, const char *fmt, ...)
-    __attribute__((format(printf,2,3)));
-static void xasprintf(char **strp, const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    xvasprintf(strp, fmt, ap);
-    va_end(ap);
-}
-
 static yajl_gen_status printf_info_one_json(yajl_gen hand, int domid,
                                             libxl_domain_config *d_config)
 {
@@ -389,19 +291,6 @@ out:
     return s;
 }
 
-static void flush_stream(FILE *fh)
-{
-    const char *fh_name =
-        fh == stdout ? "stdout" :
-        fh == stderr ? "stderr" :
-        (abort(), (const char*)0);
-
-    if (ferror(fh) || fflush(fh)) {
-        perror(fh_name);
-        exit(EXIT_FAILURE);
-    }
-}
-
 static void printf_info(enum output_format output_format,
                         int domid,
                         libxl_domain_config *d_config, FILE *fh)
@@ -3294,48 +3183,6 @@ static int64_t parse_mem_size_kb(const char *mem)
     return kbytes;
 }
 
-/*
- * Callers should use SWITCH_FOREACH_OPT in preference to calling this
- * directly.
- */
-static int def_getopt(int argc, char * const argv[],
-                      const char *optstring,
-                      const struct option *longopts,
-                      const char* helpstr, int reqargs)
-{
-    int opt;
-    const struct option def_options[] = {
-        COMMON_LONG_OPTS
-    };
-
-    if (!longopts)
-        longopts = def_options;
-
-    opterr = 0;
-    while ((opt = getopt_long(argc, argv, optstring, longopts, NULL)) == '?') {
-        if (optopt == 'h') {
-            help(helpstr);
-            exit(0);
-        }
-        fprintf(stderr, "option `%c' not supported.\n", optopt);
-        exit(2);
-    }
-    if (opt == 'h') {
-        help(helpstr);
-        exit(0);
-    }
-    if (opt != -1)
-        return opt;
-
-    if (argc - optind <= reqargs - 1) {
-        fprintf(stderr, "'xl %s' requires at least %d argument%s.\n\n",
-                helpstr, reqargs, reqargs > 1 ? "s" : "");
-        help(helpstr);
-        exit(2);
-    }
-    return -1;
-}
-
 static int set_memory_max(uint32_t domid, const char *mem)
 {
     int64_t memorykb;
@@ -4155,56 +4002,6 @@ out:
     }
 }
 
-static void print_bitmap(uint8_t *map, int maplen, FILE *stream)
-{
-    int i;
-    uint8_t pmap = 0, bitmask = 0;
-    int firstset = 0, state = 0;
-
-    for (i = 0; i < maplen; i++) {
-        if (i % 8 == 0) {
-            pmap = *map++;
-            bitmask = 1;
-        } else bitmask <<= 1;
-
-        switch (state) {
-        case 0:
-        case 2:
-            if ((pmap & bitmask) != 0) {
-                firstset = i;
-                state++;
-            }
-            continue;
-        case 1:
-        case 3:
-            if ((pmap & bitmask) == 0) {
-                fprintf(stream, "%s%d", state > 1 ? "," : "", firstset);
-                if (i - 1 > firstset)
-                    fprintf(stream, "-%d", i - 1);
-                state = 2;
-            }
-            continue;
-        }
-    }
-    switch (state) {
-        case 0:
-            fprintf(stream, "none");
-            break;
-        case 2:
-            break;
-        case 1:
-            if (firstset == 0) {
-                fprintf(stream, "all");
-                break;
-            }
-        case 3:
-            fprintf(stream, "%s%d", state > 1 ? "," : "", firstset);
-            if (i - 1 > firstset)
-                fprintf(stream, "-%d", i - 1);
-            break;
-    }
-}
-
 static void list_domains(bool verbose, bool context, bool claim, bool numa,
                          bool cpupool, const libxl_dominfo *info, int nb_domain)
 {
@@ -5331,22 +5128,6 @@ int main_vm_list(int argc, char **argv)
     return EXIT_SUCCESS;
 }
 
-static void string_realloc_append(char **accumulate, const char *more)
-{
-    /* Appends more to accumulate.  Accumulate is either NULL, or
-     * points (always) to a malloc'd nul-terminated string. */
-
-    size_t oldlen = *accumulate ? strlen(*accumulate) : 0;
-    size_t morelen = strlen(more) + 1/*nul*/;
-    if (oldlen > SSIZE_MAX || morelen > SSIZE_MAX - oldlen) {
-        fprintf(stderr,"Additional config data far too large\n");
-        exit(-ERROR_FAIL);
-    }
-
-    *accumulate = xrealloc(*accumulate, oldlen + morelen);
-    memcpy(*accumulate + oldlen, more, morelen);
-}
-
 int main_create(int argc, char **argv)
 {
     const char *filename = NULL;
diff --git a/tools/xl/xl_utils.c b/tools/xl/xl_utils.c
new file mode 100644
index 0000000000..1ebe8005ae
--- /dev/null
+++ b/tools/xl/xl_utils.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#define _GNU_SOURCE
+
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+
+extern int logfile;
+extern const char *common_domname;
+
+void dolog(const char *file, int line, const char *func, char *fmt, ...)
+{
+    va_list ap;
+    char *s = NULL;
+    int rc;
+
+    va_start(ap, fmt);
+    rc = vasprintf(&s, fmt, ap);
+    va_end(ap);
+    if (rc >= 0)
+        /* we ignore write errors since we have no way to report them;
+         * the alternative would be to abort the whole program */
+        libxl_write_exactly(NULL, logfile, s, rc, NULL, NULL);
+    free(s);
+}
+
+void xvasprintf(char **strp, const char *fmt, va_list ap)
+{
+    int r = vasprintf(strp, fmt, ap);
+    if (r == -1) {
+        perror("asprintf failed");
+        exit(EXIT_FAILURE);
+    }
+}
+
+void xasprintf(char **strp, const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    xvasprintf(strp, fmt, ap);
+    va_end(ap);
+}
+
+void *xmalloc(size_t sz)
+{
+    void *r;
+    r = malloc(sz);
+    if (!r) {
+        fprintf(stderr,"xl: Unable to malloc %lu bytes.\n",
+                (unsigned long)sz);
+        exit(-ERROR_FAIL);
+    }
+    return r;
+}
+
+void *xcalloc(size_t n, size_t sz)
+{
+    void *r = calloc(n, sz);
+    if (!r) {
+        fprintf(stderr,"xl: Unable to calloc %zu bytes.\n", sz*n);
+        exit(-ERROR_FAIL);
+    }
+    return r;
+}
+
+void *xrealloc(void *ptr, size_t sz)
+{
+    void *r;
+    if (!sz) {
+        free(ptr);
+        return 0;
+    }
+    /* realloc(non-0, 0) has a useless return value;
+     * but xrealloc(anything, 0) is like free
+     */
+    r = realloc(ptr, sz);
+    if (!r) {
+        fprintf(stderr,"xl: Unable to realloc to %lu bytes.\n",
+                (unsigned long)sz);
+        exit(-ERROR_FAIL);
+    }
+    return r;
+}
+
+char *xstrdup(const char *x)
+{
+    char *r;
+    r = strdup(x);
+    if (!r) {
+        fprintf(stderr, "xl: Unable to strdup a string of length %zu.\n",
+                strlen(x));
+        exit(-ERROR_FAIL);
+    }
+    return r;
+}
+
+void flush_stream(FILE *fh)
+{
+    const char *fh_name =
+        fh == stdout ? "stdout" :
+        fh == stderr ? "stderr" :
+        (abort(), (const char*)0);
+
+    if (ferror(fh) || fflush(fh)) {
+        perror(fh_name);
+        exit(EXIT_FAILURE);
+    }
+}
+
+uint32_t find_domain(const char *p)
+{
+    uint32_t domid;
+    int rc;
+
+    rc = libxl_domain_qualifier_to_domid(ctx, p, &domid);
+    if (rc) {
+        fprintf(stderr, "%s is an invalid domain identifier (rc=%d)\n", p, rc);
+        exit(EXIT_FAILURE);
+    }
+    common_domname = libxl_domid_to_name(ctx, domid);
+    return domid;
+}
+
+/*
+ * Callers should use SWITCH_FOREACH_OPT in preference to calling this
+ * directly.
+ */
+int def_getopt(int argc, char * const argv[],
+                const char *optstring,
+                const struct option *longopts,
+                const char* helpstr, int reqargs)
+{
+    int opt;
+    const struct option def_options[] = {
+        COMMON_LONG_OPTS
+    };
+
+    if (!longopts)
+        longopts = def_options;
+
+    opterr = 0;
+    while ((opt = getopt_long(argc, argv, optstring, longopts, NULL)) == '?') {
+        if (optopt == 'h') {
+            help(helpstr);
+            exit(0);
+        }
+        fprintf(stderr, "option `%c' not supported.\n", optopt);
+        exit(2);
+    }
+    if (opt == 'h') {
+        help(helpstr);
+        exit(0);
+    }
+    if (opt != -1)
+        return opt;
+
+    if (argc - optind <= reqargs - 1) {
+        fprintf(stderr, "'xl %s' requires at least %d argument%s.\n\n",
+                helpstr, reqargs, reqargs > 1 ? "s" : "");
+        help(helpstr);
+        exit(2);
+    }
+    return -1;
+}
+
+void string_realloc_append(char **accumulate, const char *more)
+{
+    /* Appends more to accumulate.  Accumulate is either NULL, or
+     * points (always) to a malloc'd nul-terminated string. */
+
+    size_t oldlen = *accumulate ? strlen(*accumulate) : 0;
+    size_t morelen = strlen(more) + 1/*nul*/;
+    if (oldlen > SSIZE_MAX || morelen > SSIZE_MAX - oldlen) {
+        fprintf(stderr,"Additional config data far too large\n");
+        exit(-ERROR_FAIL);
+    }
+
+    *accumulate = xrealloc(*accumulate, oldlen + morelen);
+    memcpy(*accumulate + oldlen, more, morelen);
+}
+
+void print_bitmap(uint8_t *map, int maplen, FILE *stream)
+{
+    int i;
+    uint8_t pmap = 0, bitmask = 0;
+    int firstset = 0, state = 0;
+
+    for (i = 0; i < maplen; i++) {
+        if (i % 8 == 0) {
+            pmap = *map++;
+            bitmask = 1;
+        } else bitmask <<= 1;
+
+        switch (state) {
+        case 0:
+        case 2:
+            if ((pmap & bitmask) != 0) {
+                firstset = i;
+                state++;
+            }
+            continue;
+        case 1:
+        case 3:
+            if ((pmap & bitmask) == 0) {
+                fprintf(stream, "%s%d", state > 1 ? "," : "", firstset);
+                if (i - 1 > firstset)
+                    fprintf(stream, "-%d", i - 1);
+                state = 2;
+            }
+            continue;
+        }
+    }
+    switch (state) {
+        case 0:
+            fprintf(stream, "none");
+            break;
+        case 2:
+            break;
+        case 1:
+            if (firstset == 0) {
+                fprintf(stream, "all");
+                break;
+            }
+        case 3:
+            fprintf(stream, "%s%d", state > 1 ? "," : "", firstset);
+            if (i - 1 > firstset)
+                fprintf(stream, "-%d", i - 1);
+            break;
+    }
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/xl/xl_utils.h b/tools/xl/xl_utils.h
index ebb9305b7c..a2cf138523 100644
--- a/tools/xl/xl_utils.h
+++ b/tools/xl/xl_utils.h
@@ -15,6 +15,8 @@
 #ifndef XL_UTILS_H
 #define XL_UTILS_H
 
+#include <getopt.h>
+
 /* For calls which return an errno on failure */
 #define CHK_ERRNOVAL( call ) ({                                         \
         int chk_errnoval = (call);                                      \
@@ -118,6 +120,31 @@
 #define COMMON_LONG_OPTS {"help", 0, 0, 'h'}, \
                          {0, 0, 0, 0}
 
+int def_getopt(int argc, char * const argv[],
+               const char *optstring,
+               const struct option *longopts,
+               const char* helpstr, int reqargs);
+
+void dolog(const char *file, int line, const char *func, char *fmt, ...)
+	__attribute__((format(printf,4,5)));
+
+void xvasprintf(char **strp, const char *fmt, va_list ap)
+	__attribute__((format(printf,2,0)));
+
+void xasprintf(char **strp, const char *fmt, ...)
+	__attribute__((format(printf,2,3)));
+
+void *xmalloc(size_t sz);
+void *xcalloc(size_t n, size_t sz);
+void *xrealloc(void *ptr, size_t sz);
+char *xstrdup(const char *x);
+void string_realloc_append(char **accumulate, const char *more);
+
+void flush_stream(FILE *fh);
+uint32_t find_domain(const char *p) __attribute__((warn_unused_result));
+
+void print_bitmap(uint8_t *map, int maplen, FILE *stream);
+
 #endif /* XL_UTILS_H */
 
 /*
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 1/3] xl: rename cpurange_parse to parse_cpurange
  2017-02-27 15:57   ` Ian Jackson
@ 2017-02-27 17:47     ` Wei Liu
  2017-02-27 17:47       ` [PATCH 2/3] xl: introduce a function to get shutdown action name Wei Liu
                         ` (2 more replies)
  0 siblings, 3 replies; 76+ messages in thread
From: Wei Liu @ 2017-02-27 17:47 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

We want to consistently prefix functions to parse input with "parse_".

No functional change.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/xl_cmdimpl.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index 2721af317b..86c70f5a22 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -697,7 +697,7 @@ static int update_cpumap_range(const char *str, libxl_bitmap *cpumap)
  * single cpus or as eintire NUMA nodes) and turns it into the
  * corresponding libxl_bitmap (in cpumap).
  */
-static int cpurange_parse(const char *cpu, libxl_bitmap *cpumap)
+static int parse_cpurange(const char *cpu, libxl_bitmap *cpumap)
 {
     char *ptr, *saveptr = NULL, *buf = xstrdup(cpu);
     int rc = 0;
@@ -808,7 +808,7 @@ static void parse_vcpu_affinity(libxl_domain_build_info *b_info,
                 exit(EXIT_FAILURE);
             }
 
-            if (cpurange_parse(buf, &vcpu_affinity_array[j]))
+            if (parse_cpurange(buf, &vcpu_affinity_array[j]))
                 exit(EXIT_FAILURE);
 
             j++;
@@ -825,7 +825,7 @@ static void parse_vcpu_affinity(libxl_domain_build_info *b_info,
             exit(EXIT_FAILURE);
         }
 
-        if (cpurange_parse(buf, &vcpu_affinity_array[0]))
+        if (parse_cpurange(buf, &vcpu_affinity_array[0]))
             exit(EXIT_FAILURE);
 
         for (i = 1; i < b_info->max_vcpus; i++) {
@@ -5522,7 +5522,7 @@ int main_vcpupin(int argc, char **argv)
      */
     if (!strcmp(hard_str, "-"))
         hard = NULL;
-    else if (cpurange_parse(hard_str, hard))
+    else if (parse_cpurange(hard_str, hard))
         goto out;
     /*
      * Soft affinity is handled similarly. Only difference: we also want
@@ -5530,7 +5530,7 @@ int main_vcpupin(int argc, char **argv)
      */
     if (argc <= optind+3 || !strcmp(soft_str, "-"))
         soft = NULL;
-    else if (cpurange_parse(soft_str, soft))
+    else if (parse_cpurange(soft_str, soft))
         goto out;
 
     if (dryrun_only) {
@@ -7793,7 +7793,7 @@ int main_cpupoolcreate(int argc, char **argv)
             n_cpus++;
         }
     } else if (!xlu_cfg_get_string(config, "cpus", &buf, 0)) {
-        if (cpurange_parse(buf, &cpumap))
+        if (parse_cpurange(buf, &cpumap))
             goto out_cfg;
 
         n_cpus = 0;
@@ -7974,7 +7974,7 @@ int main_cpupoolcpuadd(int argc, char **argv)
     }
 
     pool = argv[optind++];
-    if (cpurange_parse(argv[optind], &cpumap))
+    if (parse_cpurange(argv[optind], &cpumap))
         goto out;
 
     if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
@@ -8012,7 +8012,7 @@ int main_cpupoolcpuremove(int argc, char **argv)
     }
 
     pool = argv[optind++];
-    if (cpurange_parse(argv[optind], &cpumap))
+    if (parse_cpurange(argv[optind], &cpumap))
         goto out;
 
     if (libxl_cpupool_qualifier_to_cpupoolid(ctx, pool, &poolid, NULL) ||
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 2/3] xl: introduce a function to get shutdown action name
  2017-02-27 17:47     ` [PATCH 1/3] xl: rename cpurange_parse to parse_cpurange Wei Liu
@ 2017-02-27 17:47       ` Wei Liu
  2017-02-27 18:11         ` Ian Jackson
  2017-02-27 17:47       ` [PATCH 3/3] xl: split out xl_parse.[ch] Wei Liu
  2017-02-27 18:11       ` [PATCH 1/3] xl: rename cpurange_parse to parse_cpurange Ian Jackson
  2 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-27 17:47 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

The array to map libxl_shutdown_action_to_shutdown to string is going to
be moved to a dedicated file.

Provide a function to do the translation so that we don't need to make
the array globally visible.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/xl_cmdimpl.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index 86c70f5a22..d027d53a3f 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -101,6 +101,11 @@ static const char *action_on_shutdown_names[] = {
     [LIBXL_ACTION_ON_SHUTDOWN_SOFT_RESET] = "soft-reset",
 };
 
+static const char *get_action_on_shutdown_name(libxl_action_on_shutdown a)
+{
+    return action_on_shutdown_names[a];
+}
+
 /* Optional data, in order:
  *   4 bytes uint32_t  config file size
  *   n bytes           config file in Unix text file format
@@ -2442,7 +2447,7 @@ static domain_restart_type handle_domain_death(uint32_t *r_domid,
 
     LOG("Action for shutdown reason code %d is %s",
         event->u.domain_shutdown.shutdown_reason,
-        action_on_shutdown_names[action]);
+        get_action_on_shutdown_name(action));
 
     if (action == LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY || action == LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_RESTART) {
         char *corefile;
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 3/3] xl: split out xl_parse.[ch]
  2017-02-27 17:47     ` [PATCH 1/3] xl: rename cpurange_parse to parse_cpurange Wei Liu
  2017-02-27 17:47       ` [PATCH 2/3] xl: introduce a function to get shutdown action name Wei Liu
@ 2017-02-27 17:47       ` Wei Liu
  2017-02-27 18:11         ` Ian Jackson
  2017-02-27 18:11       ` [PATCH 1/3] xl: rename cpurange_parse to parse_cpurange Ian Jackson
  2 siblings, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-27 17:47 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

Move all parsing code into xl_parse.c. Export the ones needed in
xl_parse.h.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |    2 +-
 tools/xl/xl_cmdimpl.c | 2346 ++++---------------------------------------------
 tools/xl/xl_parse.c   | 2052 ++++++++++++++++++++++++++++++++++++++++++
 tools/xl/xl_parse.h   |   65 ++
 4 files changed, 2282 insertions(+), 2183 deletions(-)
 create mode 100644 tools/xl/xl_parse.c
 create mode 100644 tools/xl/xl_parse.h

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index f5df366e0a..d7f7f01549 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -16,7 +16,7 @@ CFLAGS_XL += $(CFLAGS_libxenlight)
 CFLAGS_XL += -Wshadow
 
 XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
-XL_OBJS += xl_tmem.o
+XL_OBJS += xl_tmem.o xl_parse.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index d027d53a3f..51976f94b3 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -39,6 +39,7 @@
 #include <libxlutil.h>
 #include "xl.h"
 #include "xl_utils.h"
+#include "xl_parse.h"
 
 int logfile = 2;
 
@@ -86,26 +87,6 @@ struct save_file_header {
     uint32_t optional_data_len; /* skip, or skip tail, if not understood */
 };
 
-
-static const char *action_on_shutdown_names[] = {
-    [LIBXL_ACTION_ON_SHUTDOWN_DESTROY] = "destroy",
-
-    [LIBXL_ACTION_ON_SHUTDOWN_RESTART] = "restart",
-    [LIBXL_ACTION_ON_SHUTDOWN_RESTART_RENAME] = "rename-restart",
-
-    [LIBXL_ACTION_ON_SHUTDOWN_PRESERVE] = "preserve",
-
-    [LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY] = "coredump-destroy",
-    [LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_RESTART] = "coredump-restart",
-
-    [LIBXL_ACTION_ON_SHUTDOWN_SOFT_RESET] = "soft-reset",
-};
-
-static const char *get_action_on_shutdown_name(libxl_action_on_shutdown a)
-{
-    return action_on_shutdown_names[a];
-}
-
 /* Optional data, in order:
  *   4 bytes uint32_t  config file size
  *   n bytes           config file in Unix text file format
@@ -196,2181 +177,216 @@ static int acquire_lock(void)
         return ERROR_FAIL;
     }
     if (fcntl(fd_lock, F_SETFD, FD_CLOEXEC) < 0) {
-        close(fd_lock);
-        fprintf(stderr, "cannot set cloexec to lockfile %s errno=%d\n", lockfile, errno);
-        return ERROR_FAIL;
-    }
-get_lock:
-    rc = fcntl(fd_lock, F_SETLKW, &fl);
-    if (rc < 0 && errno == EINTR)
-        goto get_lock;
-    if (rc < 0) {
-        fprintf(stderr, "cannot acquire lock %s errno=%d\n", lockfile, errno);
-        rc = ERROR_FAIL;
-    } else
-        rc = 0;
-    return rc;
-}
-
-static int release_lock(void)
-{
-    int rc;
-    struct flock fl;
-
-    /* lock not acquired */
-    if (fd_lock < 0)
-        return ERROR_INVAL;
-
-release_lock:
-    fl.l_type = F_UNLCK;
-    fl.l_whence = SEEK_SET;
-    fl.l_start = 0;
-    fl.l_len = 0;
-
-    rc = fcntl(fd_lock, F_SETLKW, &fl);
-    if (rc < 0 && errno == EINTR)
-        goto release_lock;
-    if (rc < 0) {
-        fprintf(stderr, "cannot release lock %s, errno=%d\n", lockfile, errno);
-        rc = ERROR_FAIL;
-    } else
-        rc = 0;
-    close(fd_lock);
-    fd_lock = -1;
-
-    return rc;
-}
-
-
-#define ARRAY_EXTEND_INIT__CORE(array,count,initfn,more)                \
-    ({                                                                  \
-        typeof((count)) array_extend_old_count = (count);               \
-        (count)++;                                                      \
-        (array) = xrealloc((array), sizeof(*array) * (count));          \
-        (initfn)(&(array)[array_extend_old_count]);                     \
-        more;                                                           \
-        &(array)[array_extend_old_count];                               \
-    })
-
-#define ARRAY_EXTEND_INIT(array,count,initfn)                           \
-    ARRAY_EXTEND_INIT__CORE((array),(count),(initfn), ({                \
-        (array)[array_extend_old_count].devid = array_extend_old_count; \
-        }))
-
-#define ARRAY_EXTEND_INIT_NODEVID(array,count,initfn) \
-    ARRAY_EXTEND_INIT__CORE((array),(count),(initfn), /* nothing */ )
-
-static yajl_gen_status printf_info_one_json(yajl_gen hand, int domid,
-                                            libxl_domain_config *d_config)
-{
-    yajl_gen_status s;
-
-    s = yajl_gen_map_open(hand);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_string(hand, (const unsigned char *)"domid",
-                        sizeof("domid")-1);
-    if (s != yajl_gen_status_ok)
-        goto out;
-    if (domid != -1)
-        s = yajl_gen_integer(hand, domid);
-    else
-        s = yajl_gen_null(hand);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_string(hand, (const unsigned char *)"config",
-                        sizeof("config")-1);
-    if (s != yajl_gen_status_ok)
-        goto out;
-    s = libxl_domain_config_gen_json(hand, d_config);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_map_close(hand);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-out:
-    return s;
-}
-
-static void printf_info(enum output_format output_format,
-                        int domid,
-                        libxl_domain_config *d_config, FILE *fh)
-{
-    if (output_format == OUTPUT_FORMAT_SXP)
-        return printf_info_sexp(domid, d_config, fh);
-
-    const char *buf;
-    libxl_yajl_length len = 0;
-    yajl_gen_status s;
-    yajl_gen hand;
-
-    hand = libxl_yajl_gen_alloc(NULL);
-    if (!hand) {
-        fprintf(stderr, "unable to allocate JSON generator\n");
-        return;
-    }
-
-    s = printf_info_one_json(hand, domid, d_config);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    s = yajl_gen_get_buf(hand, (const unsigned char **)&buf, &len);
-    if (s != yajl_gen_status_ok)
-        goto out;
-
-    fputs(buf, fh);
-
-out:
-    yajl_gen_free(hand);
-
-    if (s != yajl_gen_status_ok)
-        fprintf(stderr,
-                "unable to format domain config as JSON (YAJL:%d)\n", s);
-
-    flush_stream(fh);
-}
-
-static int do_daemonize(char *name, const char *pidfile)
-{
-    char *fullname;
-    pid_t child1;
-    int nullfd, ret = 0;
-
-    child1 = xl_fork(child_waitdaemon, "domain monitoring daemonizing child");
-    if (child1) {
-        ret = child_report(child_waitdaemon);
-        if (ret) goto out;
-        ret = 1;
-        goto out;
-    }
-
-    postfork();
-
-    ret = libxl_create_logfile(ctx, name, &fullname);
-    if (ret) {
-        LOG("failed to open logfile %s: %s",fullname,strerror(errno));
-        exit(-1);
-    }
-
-    CHK_SYSCALL(logfile = open(fullname, O_WRONLY|O_CREAT|O_APPEND, 0644));
-    free(fullname);
-    assert(logfile >= 3);
-
-    CHK_SYSCALL(nullfd = open("/dev/null", O_RDONLY));
-    assert(nullfd >= 3);
-
-    dup2(nullfd, 0);
-    dup2(logfile, 1);
-    dup2(logfile, 2);
-
-    close(nullfd);
-
-    CHK_SYSCALL(daemon(0, 1));
-
-    if (pidfile) {
-        int fd = open(pidfile, O_RDWR | O_CREAT, S_IRUSR|S_IWUSR);
-        char *pid = NULL;
-
-        if (fd == -1) {
-            perror("Unable to open pidfile");
-            exit(1);
-        }
-
-        if (asprintf(&pid, "%ld\n", (long)getpid()) == -1) {
-            perror("Formatting pid");
-            exit(1);
-        }
-
-        if (write(fd, pid, strlen(pid)) < 0) {
-            perror("Writing pid");
-            exit(1);
-        }
-
-        if (close(fd) < 0) {
-            perror("Closing pidfile");
-            exit(1);
-        }
-
-        free(pid);
-    }
-
-out:
-    return ret;
-}
-
-static int parse_action_on_shutdown(const char *buf, libxl_action_on_shutdown *a)
-{
-    int i;
-    const char *n;
-
-    for (i = 0; i < sizeof(action_on_shutdown_names) / sizeof(action_on_shutdown_names[0]); i++) {
-        n = action_on_shutdown_names[i];
-
-        if (!n) continue;
-
-        if (strcmp(buf, n) == 0) {
-            *a = i;
-            return 1;
-        }
-    }
-    return 0;
-}
-
-#define DSTATE_INITIAL   0
-#define DSTATE_TAP       1
-#define DSTATE_PHYSPATH  2
-#define DSTATE_VIRTPATH  3
-#define DSTATE_VIRTTYPE  4
-#define DSTATE_RW        5
-#define DSTATE_TERMINAL  6
-
-static void parse_disk_config_multistring(XLU_Config **config,
-                                          int nspecs, const char *const *specs,
-                                          libxl_device_disk *disk)
-{
-    int e;
-
-    libxl_device_disk_init(disk);
-
-    if (!*config) {
-        *config = xlu_cfg_init(stderr, "command line");
-        if (!*config) { perror("xlu_cfg_init"); exit(-1); }
-    }
-
-    e = xlu_disk_parse(*config, nspecs, specs, disk);
-    if (e == EINVAL) exit(EXIT_FAILURE);
-    if (e) {
-        fprintf(stderr,"xlu_disk_parse failed: %s\n",strerror(errno));
-        exit(EXIT_FAILURE);
-    }
-}
-
-static void parse_disk_config(XLU_Config **config, const char *spec,
-                              libxl_device_disk *disk)
-{
-    parse_disk_config_multistring(config, 1, &spec, disk);
-}
-
-static void parse_vif_rate(XLU_Config **config, const char *rate,
-                           libxl_device_nic *nic)
-{
-    int e;
-
-    e = xlu_vif_parse_rate(*config, rate, nic);
-    if (e == EINVAL || e == EOVERFLOW) exit(EXIT_FAILURE);
-    if (e) {
-        fprintf(stderr,"xlu_vif_parse_rate failed: %s\n",strerror(errno));
-        exit(EXIT_FAILURE);
-    }
-}
-
-static void set_default_nic_values(libxl_device_nic *nic)
-{
-
-    if (default_vifscript) {
-        free(nic->script);
-        nic->script = strdup(default_vifscript);
-    }
-
-    if (default_bridge) {
-        free(nic->bridge);
-        nic->bridge = strdup(default_bridge);
-    }
-
-    if (default_gatewaydev) {
-        free(nic->gatewaydev);
-        nic->gatewaydev = strdup(default_gatewaydev);
-    }
-
-    if (default_vifbackend) {
-        free(nic->backend_domname);
-        nic->backend_domname = strdup(default_vifbackend);
-    }
-}
-
-static void split_string_into_string_list(const char *str,
-                                          const char *delim,
-                                          libxl_string_list *psl)
-{
-    char *s, *saveptr;
-    const char *p;
-    libxl_string_list sl;
-
-    int i = 0, nr = 0;
-
-    s = strdup(str);
-    if (s == NULL) {
-        fprintf(stderr, "unable to allocate memory to split string\n");
-        exit(-1);
-    }
-
-    /* Count number of entries */
-    p = strtok_r(s, delim, &saveptr);
-    do {
-        nr++;
-    } while ((p = strtok_r(NULL, delim, &saveptr)));
-
-    free(s);
-
-    s = strdup(str);
-
-    sl = malloc((nr+1) * sizeof (char *));
-    if (sl == NULL) {
-        fprintf(stderr, "unable to allocate memory to split string\n");
-        exit(-1);
-    }
-
-    p = strtok_r(s, delim, &saveptr);
-    do {
-        assert(i < nr);
-        sl[i] = strdup(p);
-        i++;
-    } while ((p = strtok_r(NULL, delim, &saveptr)));
-    sl[i] = NULL;
-
-    *psl = sl;
-
-    free(s);
-}
-
-/* NB: this follows the interface used by <ctype.h>. See 'man 3 ctype'
-   and look for CTYPE in libxl_internal.h */
-typedef int (*char_predicate_t)(const int c);
-
-static void trim(char_predicate_t predicate, const char *input, char **output)
-{
-    const char *first, *after;
-
-    for (first = input;
-         *first && predicate((unsigned char)first[0]);
-         first++)
-        ;
-
-    for (after = first + strlen(first);
-         after > first && predicate((unsigned char)after[-1]);
-         after--)
-        ;
-
-    size_t len_nonnull = after - first;
-    char *result = xmalloc(len_nonnull + 1);
-
-    memcpy(result, first, len_nonnull);
-    result[len_nonnull] = 0;
-
-    *output = result;
-}
-
-static int split_string_into_pair(const char *str,
-                                  const char *delim,
-                                  char **a,
-                                  char **b)
-{
-    char *s, *p, *saveptr, *aa = NULL, *bb = NULL;
-    int rc = 0;
-
-    s = xstrdup(str);
-
-    p = strtok_r(s, delim, &saveptr);
-    if (p == NULL) {
-        rc = ERROR_INVAL;
-        goto out;
-    }
-    aa = xstrdup(p);
-    p = strtok_r(NULL, delim, &saveptr);
-    if (p == NULL) {
-        rc = ERROR_INVAL;
-        goto out;
-    }
-    bb = xstrdup(p);
-
-    *a = aa;
-    aa = NULL;
-    *b = bb;
-    bb = NULL;
-out:
-    free(s);
-    free(aa);
-    free(bb);
-    return rc;
-}
-
-static int parse_range(const char *str, unsigned long *a, unsigned long *b)
-{
-    const char *nstr;
-    char *endptr;
-
-    *a = *b = strtoul(str, &endptr, 10);
-    if (endptr == str || *a == ULONG_MAX)
-        return 1;
-
-    if (*endptr == '-') {
-        nstr = endptr + 1;
-
-        *b = strtoul(nstr, &endptr, 10);
-        if (endptr == nstr || *b == ULONG_MAX || *b < *a)
-            return 1;
-    }
-
-    /* Valid value or range so far, but we also don't want junk after that */
-    if (*endptr != '\0')
-        return 1;
-
-    return 0;
-}
-
-/*
- * Add or removes a specific set of cpus (specified in str, either as
- * single cpus or as entire NUMA nodes) to/from cpumap.
- */
-static int update_cpumap_range(const char *str, libxl_bitmap *cpumap)
-{
-    unsigned long ida, idb;
-    libxl_bitmap node_cpumap;
-    bool is_not = false, is_nodes = false;
-    int rc = 0;
-
-    libxl_bitmap_init(&node_cpumap);
-
-    rc = libxl_node_bitmap_alloc(ctx, &node_cpumap, 0);
-    if (rc) {
-        fprintf(stderr, "libxl_node_bitmap_alloc failed.\n");
-        goto out;
-    }
-
-    /* Are we adding or removing cpus/nodes? */
-    if (STR_SKIP_PREFIX(str, "^")) {
-        is_not = true;
-    }
-
-    /* Are we dealing with cpus or full nodes? */
-    if (STR_SKIP_PREFIX(str, "node:") || STR_SKIP_PREFIX(str, "nodes:")) {
-        is_nodes = true;
-    }
-
-    if (strcmp(str, "all") == 0) {
-        /* We do not accept "^all" or "^nodes:all" */
-        if (is_not) {
-            fprintf(stderr, "Can't combine \"^\" and \"all\".\n");
-            rc = ERROR_INVAL;
-        } else
-            libxl_bitmap_set_any(cpumap);
-        goto out;
-    }
-
-    rc = parse_range(str, &ida, &idb);
-    if (rc) {
-        fprintf(stderr, "Invalid pcpu range: %s.\n", str);
-        goto out;
-    }
-
-    /* Add or remove the specified cpus in the range */
-    while (ida <= idb) {
-        if (is_nodes) {
-            /* Add/Remove all the cpus of a NUMA node */
-            int i;
-
-            rc = libxl_node_to_cpumap(ctx, ida, &node_cpumap);
-            if (rc) {
-                fprintf(stderr, "libxl_node_to_cpumap failed.\n");
-                goto out;
-            }
-
-            /* Add/Remove all the cpus in the node cpumap */
-            libxl_for_each_set_bit(i, node_cpumap) {
-                is_not ? libxl_bitmap_reset(cpumap, i) :
-                         libxl_bitmap_set(cpumap, i);
-            }
-        } else {
-            /* Add/Remove this cpu */
-            is_not ? libxl_bitmap_reset(cpumap, ida) :
-                     libxl_bitmap_set(cpumap, ida);
-        }
-        ida++;
-    }
-
- out:
-    libxl_bitmap_dispose(&node_cpumap);
-    return rc;
-}
-
-/*
- * Takes a string representing a set of cpus (specified either as
- * single cpus or as eintire NUMA nodes) and turns it into the
- * corresponding libxl_bitmap (in cpumap).
- */
-static int parse_cpurange(const char *cpu, libxl_bitmap *cpumap)
-{
-    char *ptr, *saveptr = NULL, *buf = xstrdup(cpu);
-    int rc = 0;
-
-    for (ptr = strtok_r(buf, ",", &saveptr); ptr;
-         ptr = strtok_r(NULL, ",", &saveptr)) {
-        rc = update_cpumap_range(ptr, cpumap);
-        if (rc)
-            break;
-    }
-    free(buf);
-
-    return rc;
-}
-
-static void parse_top_level_vnc_options(XLU_Config *config,
-                                        libxl_vnc_info *vnc)
-{
-    long l;
-
-    xlu_cfg_get_defbool(config, "vnc", &vnc->enable, 0);
-    xlu_cfg_replace_string (config, "vnclisten", &vnc->listen, 0);
-    xlu_cfg_replace_string (config, "vncpasswd", &vnc->passwd, 0);
-    if (!xlu_cfg_get_long (config, "vncdisplay", &l, 0))
-        vnc->display = l;
-    xlu_cfg_get_defbool(config, "vncunused", &vnc->findunused, 0);
-}
-
-static void parse_top_level_sdl_options(XLU_Config *config,
-                                        libxl_sdl_info *sdl)
-{
-    xlu_cfg_get_defbool(config, "sdl", &sdl->enable, 0);
-    xlu_cfg_get_defbool(config, "opengl", &sdl->opengl, 0);
-    xlu_cfg_replace_string (config, "display", &sdl->display, 0);
-    xlu_cfg_replace_string (config, "xauthority", &sdl->xauthority, 0);
-}
-
-static char *parse_cmdline(XLU_Config *config)
-{
-    char *cmdline = NULL;
-    const char *root = NULL, *extra = NULL, *buf = NULL;
-
-    xlu_cfg_get_string (config, "cmdline", &buf, 0);
-    xlu_cfg_get_string (config, "root", &root, 0);
-    xlu_cfg_get_string (config, "extra", &extra, 0);
-
-    if (buf) {
-        cmdline = strdup(buf);
-        if (root || extra)
-            fprintf(stderr, "Warning: ignoring root= and extra= "
-                    "in favour of cmdline=\n");
-    } else {
-        if (root && extra) {
-            xasprintf(&cmdline, "root=%s %s", root, extra);
-        } else if (root) {
-            xasprintf(&cmdline, "root=%s", root);
-        } else if (extra) {
-            cmdline = strdup(extra);
-        }
-    }
-
-    if ((buf || root || extra) && !cmdline) {
-        fprintf(stderr, "Failed to allocate memory for cmdline\n");
-        exit(EXIT_FAILURE);
-    }
-
-    return cmdline;
-}
-
-static void parse_vcpu_affinity(libxl_domain_build_info *b_info,
-                                XLU_ConfigList *cpus, const char *buf,
-                                int num_cpus, bool is_hard)
-{
-    libxl_bitmap *vcpu_affinity_array;
-
-    /*
-     * If we are here, and buf is !NULL, we're dealing with a string. What
-     * we do in this case is parse it, and copy the result in _all_ (up to
-     * b_info->max_vcpus) the elements of the vcpu affinity array.
-     *
-     * If buf is NULL, we have a list, and what we do is putting in the
-     * i-eth element of the vcpu affinity array the result of the parsing
-     * of the i-eth entry of the list. If there are more vcpus than
-     * entries, it is fine to just not touch the last array elements.
-     */
-
-    /* Silently ignore values corresponding to non existing vcpus */
-    if (buf || num_cpus > b_info->max_vcpus)
-        num_cpus = b_info->max_vcpus;
-
-    if (is_hard) {
-        b_info->num_vcpu_hard_affinity = num_cpus;
-        b_info->vcpu_hard_affinity = xmalloc(num_cpus * sizeof(libxl_bitmap));
-        vcpu_affinity_array = b_info->vcpu_hard_affinity;
-    } else {
-        b_info->num_vcpu_soft_affinity = num_cpus;
-        b_info->vcpu_soft_affinity = xmalloc(num_cpus * sizeof(libxl_bitmap));
-        vcpu_affinity_array = b_info->vcpu_soft_affinity;
-    }
-
-    if (!buf) {
-        int j = 0;
-
-        while ((buf = xlu_cfg_get_listitem(cpus, j)) != NULL && j < num_cpus) {
-            libxl_bitmap_init(&vcpu_affinity_array[j]);
-            if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[j], 0)) {
-                fprintf(stderr, "Unable to allocate cpumap for vcpu %d\n", j);
-                exit(EXIT_FAILURE);
-            }
-
-            if (parse_cpurange(buf, &vcpu_affinity_array[j]))
-                exit(EXIT_FAILURE);
-
-            j++;
-        }
-
-        /* We have a list of cpumaps, disable automatic placement */
-        libxl_defbool_set(&b_info->numa_placement, false);
-    } else {
-        int i;
-
-        libxl_bitmap_init(&vcpu_affinity_array[0]);
-        if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[0], 0)) {
-            fprintf(stderr, "Unable to allocate cpumap for vcpu 0\n");
-            exit(EXIT_FAILURE);
-        }
-
-        if (parse_cpurange(buf, &vcpu_affinity_array[0]))
-            exit(EXIT_FAILURE);
-
-        for (i = 1; i < b_info->max_vcpus; i++) {
-            libxl_bitmap_init(&vcpu_affinity_array[i]);
-            if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[i], 0)) {
-                fprintf(stderr, "Unable to allocate cpumap for vcpu %d\n", i);
-                exit(EXIT_FAILURE);
-            }
-            libxl_bitmap_copy(ctx, &vcpu_affinity_array[i],
-                              &vcpu_affinity_array[0]);
-        }
-
-        libxl_defbool_set(&b_info->numa_placement, false);
-    }
-}
-
-static unsigned long parse_ulong(const char *str)
-{
-    char *endptr;
-    unsigned long val;
-
-    val = strtoul(str, &endptr, 10);
-    if (endptr == str || val == ULONG_MAX) {
-        fprintf(stderr, "xl: failed to convert \"%s\" to number\n", str);
-        exit(EXIT_FAILURE);
-    }
-    return val;
-}
-
-static void replace_string(char **str, const char *val)
-{
-    free(*str);
-    *str = xstrdup(val);
-}
-
-static int match_option_size(const char *prefix, size_t len,
-        char *arg, char **argopt)
-{
-    int rc = strncmp(prefix, arg, len);
-    if (!rc) *argopt = arg+len;
-    return !rc;
-}
-#define MATCH_OPTION(prefix, arg, oparg) \
-    match_option_size((prefix "="), sizeof((prefix)), (arg), &(oparg))
-
-/* Parses network data and adds info into nic
- * Returns 1 if the input token does not match one of the keys
- * or parsed values are not correct. Successful parse returns 0 */
-static int parse_nic_config(libxl_device_nic *nic, XLU_Config **config, char *token)
-{
-    char *endptr, *oparg;
-    int i;
-    unsigned int val;
-
-    if (MATCH_OPTION("type", token, oparg)) {
-        if (!strcmp("vif", oparg)) {
-            nic->nictype = LIBXL_NIC_TYPE_VIF;
-        } else if (!strcmp("ioemu", oparg)) {
-            nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU;
-        } else {
-            fprintf(stderr, "Invalid parameter `type'.\n");
-            return 1;
-        }
-    } else if (MATCH_OPTION("mac", token, oparg)) {
-        for (i = 0; i < 6; i++) {
-            val = strtoul(oparg, &endptr, 16);
-            if ((oparg == endptr) || (val > 255)) {
-                fprintf(stderr, "Invalid parameter `mac'.\n");
-                return 1;
-            }
-            nic->mac[i] = val;
-            oparg = endptr + 1;
-        }
-    } else if (MATCH_OPTION("bridge", token, oparg)) {
-        replace_string(&nic->bridge, oparg);
-    } else if (MATCH_OPTION("netdev", token, oparg)) {
-        fprintf(stderr, "the netdev parameter is deprecated, "
-                        "please use gatewaydev instead\n");
-        replace_string(&nic->gatewaydev, oparg);
-    } else if (MATCH_OPTION("gatewaydev", token, oparg)) {
-        replace_string(&nic->gatewaydev, oparg);
-    } else if (MATCH_OPTION("ip", token, oparg)) {
-        replace_string(&nic->ip, oparg);
-    } else if (MATCH_OPTION("script", token, oparg)) {
-        replace_string(&nic->script, oparg);
-    } else if (MATCH_OPTION("backend", token, oparg)) {
-        replace_string(&nic->backend_domname, oparg);
-    } else if (MATCH_OPTION("vifname", token, oparg)) {
-        replace_string(&nic->ifname, oparg);
-    } else if (MATCH_OPTION("model", token, oparg)) {
-        replace_string(&nic->model, oparg);
-    } else if (MATCH_OPTION("rate", token, oparg)) {
-        parse_vif_rate(config, oparg, nic);
-    } else if (MATCH_OPTION("forwarddev", token, oparg)) {
-        replace_string(&nic->coloft_forwarddev, oparg);
-    } else if (MATCH_OPTION("accel", token, oparg)) {
-        fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
-    } else if (MATCH_OPTION("devid", token, oparg)) {
-        nic->devid = parse_ulong(oparg);
-    } else {
-        fprintf(stderr, "unrecognized argument `%s'\n", token);
-        return 1;
-    }
-    return 0;
-}
-
-static void parse_vnuma_config(const XLU_Config *config,
-                               libxl_domain_build_info *b_info)
-{
-    libxl_physinfo physinfo;
-    uint32_t nr_nodes;
-    XLU_ConfigList *vnuma;
-    int i, j, len, num_vnuma;
-    unsigned long max_vcpus = 0, max_memkb = 0;
-    /* Temporary storage for parsed vcpus information to avoid
-     * parsing config twice. This array has num_vnuma elements.
-     */
-    libxl_bitmap *vcpu_parsed;
-
-    libxl_physinfo_init(&physinfo);
-    if (libxl_get_physinfo(ctx, &physinfo) != 0) {
-        libxl_physinfo_dispose(&physinfo);
-        fprintf(stderr, "libxl_get_physinfo failed\n");
-        exit(EXIT_FAILURE);
-    }
-
-    nr_nodes = physinfo.nr_nodes;
-    libxl_physinfo_dispose(&physinfo);
-
-    if (xlu_cfg_get_list(config, "vnuma", &vnuma, &num_vnuma, 1))
-        return;
-
-    if (!num_vnuma)
-        return;
-
-    b_info->num_vnuma_nodes = num_vnuma;
-    b_info->vnuma_nodes = xcalloc(num_vnuma, sizeof(libxl_vnode_info));
-    vcpu_parsed = xcalloc(num_vnuma, sizeof(libxl_bitmap));
-    for (i = 0; i < num_vnuma; i++) {
-        libxl_bitmap_init(&vcpu_parsed[i]);
-        if (libxl_cpu_bitmap_alloc(ctx, &vcpu_parsed[i], b_info->max_vcpus)) {
-            fprintf(stderr, "libxl_node_bitmap_alloc failed.\n");
-            exit(EXIT_FAILURE);
-        }
-    }
-
-    for (i = 0; i < b_info->num_vnuma_nodes; i++) {
-        libxl_vnode_info *p = &b_info->vnuma_nodes[i];
-
-        libxl_vnode_info_init(p);
-        p->distances = xcalloc(b_info->num_vnuma_nodes,
-                               sizeof(*p->distances));
-        p->num_distances = b_info->num_vnuma_nodes;
-    }
-
-    for (i = 0; i < num_vnuma; i++) {
-        XLU_ConfigValue *vnode_spec, *conf_option;
-        XLU_ConfigList *vnode_config_list;
-        int conf_count;
-        libxl_vnode_info *p = &b_info->vnuma_nodes[i];
-
-        vnode_spec = xlu_cfg_get_listitem2(vnuma, i);
-        assert(vnode_spec);
-
-        xlu_cfg_value_get_list(config, vnode_spec, &vnode_config_list, 0);
-        if (!vnode_config_list) {
-            fprintf(stderr, "xl: cannot get vnode config option list\n");
-            exit(EXIT_FAILURE);
-        }
-
-        for (conf_count = 0;
-             (conf_option =
-              xlu_cfg_get_listitem2(vnode_config_list, conf_count));
-             conf_count++) {
-
-            if (xlu_cfg_value_type(conf_option) == XLU_STRING) {
-                char *buf, *option_untrimmed, *value_untrimmed;
-                char *option, *value;
-                unsigned long val;
-
-                xlu_cfg_value_get_string(config, conf_option, &buf, 0);
-
-                if (!buf) continue;
-
-                if (split_string_into_pair(buf, "=",
-                                           &option_untrimmed,
-                                           &value_untrimmed)) {
-                    fprintf(stderr, "xl: failed to split \"%s\" into pair\n",
-                            buf);
-                    exit(EXIT_FAILURE);
-                }
-                trim(isspace, option_untrimmed, &option);
-                trim(isspace, value_untrimmed, &value);
-
-                if (!strcmp("pnode", option)) {
-                    val = parse_ulong(value);
-                    if (val >= nr_nodes) {
-                        fprintf(stderr,
-                                "xl: invalid pnode number: %lu\n", val);
-                        exit(EXIT_FAILURE);
-                    }
-                    p->pnode = val;
-                    libxl_defbool_set(&b_info->numa_placement, false);
-                } else if (!strcmp("size", option)) {
-                    val = parse_ulong(value);
-                    p->memkb = val << 10;
-                    max_memkb += p->memkb;
-                } else if (!strcmp("vcpus", option)) {
-                    libxl_string_list cpu_spec_list;
-                    unsigned long s, e;
-
-                    split_string_into_string_list(value, ",", &cpu_spec_list);
-                    len = libxl_string_list_length(&cpu_spec_list);
-
-                    for (j = 0; j < len; j++) {
-                        parse_range(cpu_spec_list[j], &s, &e);
-                        for (; s <= e; s++) {
-                            /*
-                             * Note that if we try to set a bit beyond
-                             * the size of bitmap, libxl_bitmap_set
-                             * has no effect. The resulted bitmap
-                             * doesn't reflect what user wants. The
-                             * fallout is dealt with later after
-                             * parsing.
-                             */
-                            libxl_bitmap_set(&vcpu_parsed[i], s);
-                            max_vcpus++;
-                        }
-                    }
-
-                    libxl_string_list_dispose(&cpu_spec_list);
-                } else if (!strcmp("vdistances", option)) {
-                    libxl_string_list vdist;
-
-                    split_string_into_string_list(value, ",", &vdist);
-                    len = libxl_string_list_length(&vdist);
-
-                    for (j = 0; j < len; j++) {
-                        val = parse_ulong(vdist[j]);
-                        p->distances[j] = val;
-                    }
-                    libxl_string_list_dispose(&vdist);
-                }
-                free(option);
-                free(value);
-                free(option_untrimmed);
-                free(value_untrimmed);
-            }
-        }
-    }
-
-    /* User has specified maxvcpus= */
-    if (b_info->max_vcpus != 0) {
-        if (b_info->max_vcpus != max_vcpus) {
-            fprintf(stderr, "xl: vnuma vcpus and maxvcpus= mismatch\n");
-            exit(EXIT_FAILURE);
-        }
-    } else {
-        int host_cpus = libxl_get_online_cpus(ctx);
-
-        if (host_cpus < 0) {
-            fprintf(stderr, "Failed to get online cpus\n");
-            exit(EXIT_FAILURE);
-        }
-
-        if (host_cpus < max_vcpus) {
-            fprintf(stderr, "xl: vnuma specifies more vcpus than pcpus, "\
-                    "use maxvcpus= to override this check.\n");
-            exit(EXIT_FAILURE);
-        }
-
-        b_info->max_vcpus = max_vcpus;
-    }
-
-    /* User has specified maxmem= */
-    if (b_info->max_memkb != LIBXL_MEMKB_DEFAULT &&
-        b_info->max_memkb != max_memkb) {
-        fprintf(stderr, "xl: maxmem and vnuma memory size mismatch\n");
-        exit(EXIT_FAILURE);
-    } else
-        b_info->max_memkb = max_memkb;
-
-    for (i = 0; i < b_info->num_vnuma_nodes; i++) {
-        libxl_vnode_info *p = &b_info->vnuma_nodes[i];
-
-        libxl_bitmap_copy_alloc(ctx, &p->vcpus, &vcpu_parsed[i]);
-        libxl_bitmap_dispose(&vcpu_parsed[i]);
-    }
-
-    free(vcpu_parsed);
-}
-
-/* Parses usbctrl data and adds info into usbctrl
- * Returns 1 if the input token does not match one of the keys
- * or parsed values are not correct. Successful parse returns 0 */
-static int parse_usbctrl_config(libxl_device_usbctrl *usbctrl, char *token)
-{
-    char *oparg;
-
-    if (MATCH_OPTION("type", token, oparg)) {
-        if (libxl_usbctrl_type_from_string(oparg, &usbctrl->type)) {
-            fprintf(stderr, "Invalid usb controller type '%s'\n", oparg);
-            return 1;
-        }
-    } else if (MATCH_OPTION("version", token, oparg)) {
-        usbctrl->version = atoi(oparg);
-    } else if (MATCH_OPTION("ports", token, oparg)) {
-        usbctrl->ports = atoi(oparg);
-    } else {
-        fprintf(stderr, "Unknown string `%s' in usbctrl spec\n", token);
-        return 1;
-    }
-
-    return 0;
-}
-
-/* Parses usbdev data and adds info into usbdev
- * Returns 1 if the input token does not match one of the keys
- * or parsed values are not correct. Successful parse returns 0 */
-static int parse_usbdev_config(libxl_device_usbdev *usbdev, char *token)
-{
-    char *oparg;
-
-    if (MATCH_OPTION("type", token, oparg)) {
-        if (libxl_usbdev_type_from_string(oparg, &usbdev->type)) {
-            fprintf(stderr, "Invalid usb device type: %s\n", optarg);
-            return 1;
-        }
-    } else if (MATCH_OPTION("hostbus", token, oparg)) {
-        usbdev->u.hostdev.hostbus = strtoul(oparg, NULL, 0);
-    } else if (MATCH_OPTION("hostaddr", token, oparg)) {
-        usbdev->u.hostdev.hostaddr = strtoul(oparg, NULL, 0);
-    } else if (MATCH_OPTION("controller", token, oparg)) {
-        usbdev->ctrl = atoi(oparg);
-    } else if (MATCH_OPTION("port", token, oparg)) {
-        usbdev->port = atoi(oparg);
-    } else {
-        fprintf(stderr, "Unknown string `%s' in usbdev spec\n", token);
-        return 1;
-    }
-
-    return 0;
-}
-
-static void parse_config_data(const char *config_source,
-                              const char *config_data,
-                              int config_len,
-                              libxl_domain_config *d_config)
-{
-    const char *buf;
-    long l, vcpus = 0;
-    XLU_Config *config;
-    XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms,
-                   *usbctrls, *usbdevs;
-    XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs;
-    int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian;
-    int pci_power_mgmt = 0;
-    int pci_msitranslate = 0;
-    int pci_permissive = 0;
-    int pci_seize = 0;
-    int i, e;
-    char *kernel_basename;
-
-    libxl_domain_create_info *c_info = &d_config->c_info;
-    libxl_domain_build_info *b_info = &d_config->b_info;
-
-    config= xlu_cfg_init(stderr, config_source);
-    if (!config) {
-        fprintf(stderr, "Failed to allocate for configuration\n");
-        exit(1);
-    }
-
-    e= xlu_cfg_readdata(config, config_data, config_len);
-    if (e) {
-        fprintf(stderr, "Failed to parse config: %s\n", strerror(e));
-        exit(1);
-    }
-
-    if (!xlu_cfg_get_string (config, "init_seclabel", &buf, 0))
-        xlu_cfg_replace_string(config, "init_seclabel",
-                               &c_info->ssid_label, 0);
-
-    if (!xlu_cfg_get_string (config, "seclabel", &buf, 0)) {
-        if (c_info->ssid_label)
-            xlu_cfg_replace_string(config, "seclabel",
-                                   &b_info->exec_ssid_label, 0);
-        else
-            xlu_cfg_replace_string(config, "seclabel",
-                                   &c_info->ssid_label, 0);
-    }
-
-    libxl_defbool_set(&c_info->run_hotplug_scripts, run_hotplug_scripts);
-    c_info->type = LIBXL_DOMAIN_TYPE_PV;
-    if (!xlu_cfg_get_string (config, "builder", &buf, 0) &&
-        !strncmp(buf, "hvm", strlen(buf)))
-        c_info->type = LIBXL_DOMAIN_TYPE_HVM;
-
-    xlu_cfg_get_defbool(config, "pvh", &c_info->pvh, 0);
-    xlu_cfg_get_defbool(config, "hap", &c_info->hap, 0);
-
-    if (xlu_cfg_replace_string (config, "name", &c_info->name, 0)) {
-        fprintf(stderr, "Domain name must be specified.\n");
-        exit(1);
-    }
-
-    if (!xlu_cfg_get_string (config, "uuid", &buf, 0) ) {
-        if ( libxl_uuid_from_string(&c_info->uuid, buf) ) {
-            fprintf(stderr, "Failed to parse UUID: %s\n", buf);
-            exit(1);
-        }
-    }else{
-        libxl_uuid_generate(&c_info->uuid);
-    }
-
-    xlu_cfg_get_defbool(config, "oos", &c_info->oos, 0);
-
-    if (!xlu_cfg_get_string (config, "pool", &buf, 0))
-        xlu_cfg_replace_string(config, "pool", &c_info->pool_name, 0);
-
-    libxl_domain_build_info_init_type(b_info, c_info->type);
-    if (blkdev_start)
-        b_info->blkdev_start = strdup(blkdev_start);
-
-    /* the following is the actual config parsing with overriding
-     * values in the structures */
-    if (!xlu_cfg_get_long (config, "cpu_weight", &l, 0))
-        b_info->sched_params.weight = l;
-    if (!xlu_cfg_get_long (config, "cap", &l, 0))
-        b_info->sched_params.cap = l;
-    if (!xlu_cfg_get_long (config, "period", &l, 0))
-        b_info->sched_params.period = l;
-    if (!xlu_cfg_get_long (config, "slice", &l, 0))
-        b_info->sched_params.slice = l;
-    if (!xlu_cfg_get_long (config, "latency", &l, 0))
-        b_info->sched_params.latency = l;
-    if (!xlu_cfg_get_long (config, "extratime", &l, 0))
-        b_info->sched_params.extratime = l;
-
-    if (!xlu_cfg_get_long (config, "memory", &l, 0))
-        b_info->target_memkb = l * 1024;
-
-    if (!xlu_cfg_get_long (config, "maxmem", &l, 0))
-        b_info->max_memkb = l * 1024;
-
-    if (!xlu_cfg_get_long (config, "vcpus", &l, 0)) {
-        vcpus = l;
-        if (libxl_cpu_bitmap_alloc(ctx, &b_info->avail_vcpus, l)) {
-            fprintf(stderr, "Unable to allocate cpumap\n");
-            exit(1);
-        }
-        libxl_bitmap_set_none(&b_info->avail_vcpus);
-        while (l-- > 0)
-            libxl_bitmap_set((&b_info->avail_vcpus), l);
-    }
-
-    if (!xlu_cfg_get_long (config, "maxvcpus", &l, 0))
-        b_info->max_vcpus = l;
-
-    parse_vnuma_config(config, b_info);
-
-    /* Set max_memkb to target_memkb and max_vcpus to avail_vcpus if
-     * they are not set by user specified config option or vnuma.
-     */
-    if (b_info->max_memkb == LIBXL_MEMKB_DEFAULT)
-        b_info->max_memkb = b_info->target_memkb;
-    if (b_info->max_vcpus == 0)
-        b_info->max_vcpus = vcpus;
-
-    if (b_info->max_vcpus < vcpus) {
-        fprintf(stderr, "xl: maxvcpus < vcpus\n");
-        exit(1);
-    }
-
-    buf = NULL;
-    if (!xlu_cfg_get_list (config, "cpus", &cpus, &num_cpus, 1) ||
-        !xlu_cfg_get_string (config, "cpus", &buf, 0))
-        parse_vcpu_affinity(b_info, cpus, buf, num_cpus, /* is_hard */ true);
-
-    buf = NULL;
-    if (!xlu_cfg_get_list (config, "cpus_soft", &cpus, &num_cpus, 1) ||
-        !xlu_cfg_get_string (config, "cpus_soft", &buf, 0))
-        parse_vcpu_affinity(b_info, cpus, buf, num_cpus, false);
-
-    libxl_defbool_set(&b_info->claim_mode, claim_mode);
-
-    if (xlu_cfg_get_string (config, "on_poweroff", &buf, 0))
-        buf = "destroy";
-    if (!parse_action_on_shutdown(buf, &d_config->on_poweroff)) {
-        fprintf(stderr, "Unknown on_poweroff action \"%s\" specified\n", buf);
-        exit(1);
-    }
-
-    if (xlu_cfg_get_string (config, "on_reboot", &buf, 0))
-        buf = "restart";
-    if (!parse_action_on_shutdown(buf, &d_config->on_reboot)) {
-        fprintf(stderr, "Unknown on_reboot action \"%s\" specified\n", buf);
-        exit(1);
-    }
-
-    if (xlu_cfg_get_string (config, "on_watchdog", &buf, 0))
-        buf = "destroy";
-    if (!parse_action_on_shutdown(buf, &d_config->on_watchdog)) {
-        fprintf(stderr, "Unknown on_watchdog action \"%s\" specified\n", buf);
-        exit(1);
-    }
-
-
-    if (xlu_cfg_get_string (config, "on_crash", &buf, 0))
-        buf = "destroy";
-    if (!parse_action_on_shutdown(buf, &d_config->on_crash)) {
-        fprintf(stderr, "Unknown on_crash action \"%s\" specified\n", buf);
-        exit(1);
-    }
-
-    if (xlu_cfg_get_string (config, "on_soft_reset", &buf, 0))
-        buf = "soft-reset";
-    if (!parse_action_on_shutdown(buf, &d_config->on_soft_reset)) {
-        fprintf(stderr, "Unknown on_soft_reset action \"%s\" specified\n", buf);
-        exit(1);
-    }
-
-    /* libxl_get_required_shadow_memory() must be called after final values
-     * (default or specified) for vcpus and memory are set, because the
-     * calculation depends on those values. */
-    b_info->shadow_memkb = !xlu_cfg_get_long(config, "shadow_memory", &l, 0)
-        ? l * 1024
-        : libxl_get_required_shadow_memory(b_info->max_memkb,
-                                           b_info->max_vcpus);
-
-    xlu_cfg_get_defbool(config, "nomigrate", &b_info->disable_migrate, 0);
-
-    if (!xlu_cfg_get_long(config, "tsc_mode", &l, 1)) {
-        const char *s = libxl_tsc_mode_to_string(l);
-        fprintf(stderr, "WARNING: specifying \"tsc_mode\" as an integer is deprecated. "
-                "Please use the named parameter variant. %s%s%s\n",
-                s ? "e.g. tsc_mode=\"" : "",
-                s ? s : "",
-                s ? "\"" : "");
-
-        if (l < LIBXL_TSC_MODE_DEFAULT ||
-            l > LIBXL_TSC_MODE_NATIVE_PARAVIRT) {
-            fprintf(stderr, "ERROR: invalid value %ld for \"tsc_mode\"\n", l);
-            exit (1);
-        }
-        b_info->tsc_mode = l;
-    } else if (!xlu_cfg_get_string(config, "tsc_mode", &buf, 0)) {
-        fprintf(stderr, "got a tsc mode string: \"%s\"\n", buf);
-        if (libxl_tsc_mode_from_string(buf, &b_info->tsc_mode)) {
-            fprintf(stderr, "ERROR: invalid value \"%s\" for \"tsc_mode\"\n",
-                    buf);
-            exit (1);
-        }
-    }
-
-    if (!xlu_cfg_get_long(config, "rtc_timeoffset", &l, 0))
-        b_info->rtc_timeoffset = l;
-
-    if (!xlu_cfg_get_long(config, "vncviewer", &l, 0))
-        fprintf(stderr, "WARNING: ignoring \"vncviewer\" option. "
-                "Use \"-V\" option of \"xl create\" to automatically spawn vncviewer.\n");
-
-    xlu_cfg_get_defbool(config, "localtime", &b_info->localtime, 0);
-
-    if (!xlu_cfg_get_long (config, "videoram", &l, 0))
-        b_info->video_memkb = l * 1024;
-
-    if (!xlu_cfg_get_long(config, "max_event_channels", &l, 0))
-        b_info->event_channels = l;
-
-    xlu_cfg_replace_string (config, "kernel", &b_info->kernel, 0);
-    xlu_cfg_replace_string (config, "ramdisk", &b_info->ramdisk, 0);
-    xlu_cfg_replace_string (config, "device_tree", &b_info->device_tree, 0);
-    b_info->cmdline = parse_cmdline(config);
-
-    xlu_cfg_get_defbool(config, "driver_domain", &c_info->driver_domain, 0);
-    xlu_cfg_get_defbool(config, "acpi", &b_info->acpi, 0);
-
-    switch(b_info->type) {
-    case LIBXL_DOMAIN_TYPE_HVM:
-        kernel_basename = libxl_basename(b_info->kernel);
-        if (!strcmp(kernel_basename, "hvmloader")) {
-            fprintf(stderr, "WARNING: you seem to be using \"kernel\" "
-                    "directive to override HVM guest firmware. Ignore "
-                    "that. Use \"firmware_override\" instead if you "
-                    "really want a non-default firmware\n");
-            b_info->kernel = NULL;
-        }
-        free(kernel_basename);
-
-        xlu_cfg_replace_string (config, "firmware_override",
-                                &b_info->u.hvm.firmware, 0);
-        xlu_cfg_replace_string (config, "bios_path_override",
-                                &b_info->u.hvm.system_firmware, 0);
-        if (!xlu_cfg_get_string(config, "bios", &buf, 0)) {
-            if (libxl_bios_type_from_string(buf, &b_info->u.hvm.bios)) {
-                fprintf(stderr, "ERROR: invalid value \"%s\" for \"bios\"\n",
-                    buf);
-                exit (1);
-            }
-        } else if (b_info->u.hvm.system_firmware)
-            fprintf(stderr, "WARNING: "
-                    "bios_path_override given without specific bios name\n");
-
-        xlu_cfg_get_defbool(config, "pae", &b_info->u.hvm.pae, 0);
-        xlu_cfg_get_defbool(config, "apic", &b_info->u.hvm.apic, 0);
-        xlu_cfg_get_defbool(config, "acpi_s3", &b_info->u.hvm.acpi_s3, 0);
-        xlu_cfg_get_defbool(config, "acpi_s4", &b_info->u.hvm.acpi_s4, 0);
-        xlu_cfg_get_defbool(config, "nx", &b_info->u.hvm.nx, 0);
-        xlu_cfg_get_defbool(config, "hpet", &b_info->u.hvm.hpet, 0);
-        xlu_cfg_get_defbool(config, "vpt_align", &b_info->u.hvm.vpt_align, 0);
-
-        switch (xlu_cfg_get_list(config, "viridian",
-                                 &viridian, &num_viridian, 1))
-        {
-        case 0: /* Success */
-            if (num_viridian) {
-                libxl_bitmap_alloc(ctx, &b_info->u.hvm.viridian_enable,
-                                   LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
-                libxl_bitmap_alloc(ctx, &b_info->u.hvm.viridian_disable,
-                                   LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
-            }
-            for (i = 0; i < num_viridian; i++) {
-                libxl_viridian_enlightenment v;
-
-                buf = xlu_cfg_get_listitem(viridian, i);
-                if (strcmp(buf, "all") == 0)
-                    libxl_bitmap_set_any(&b_info->u.hvm.viridian_enable);
-                else if (strcmp(buf, "defaults") == 0)
-                    libxl_defbool_set(&b_info->u.hvm.viridian, true);
-                else {
-                    libxl_bitmap *s = &b_info->u.hvm.viridian_enable;
-                    libxl_bitmap *r = &b_info->u.hvm.viridian_disable;
-
-                    if (*buf == '!') {
-                        s = &b_info->u.hvm.viridian_disable;
-                        r = &b_info->u.hvm.viridian_enable;
-                        buf++;
-                    }
-
-                    e = libxl_viridian_enlightenment_from_string(buf, &v);
-                    if (e) {
-                        fprintf(stderr,
-                                "xl: unknown viridian enlightenment '%s'\n",
-                                buf);
-                        exit(-ERROR_FAIL);
-                    }
-
-                    libxl_bitmap_set(s, v);
-                    libxl_bitmap_reset(r, v);
-                }
-            }
-            break;
-        case ESRCH: break; /* Option not present */
-        case EINVAL:
-            xlu_cfg_get_defbool(config, "viridian", &b_info->u.hvm.viridian, 1);
-            break;
-        default:
-            fprintf(stderr,"xl: Unable to parse viridian enlightenments.\n");
-            exit(-ERROR_FAIL);
-        }
-
-        if (!xlu_cfg_get_long(config, "mmio_hole", &l, 0)) {
-            uint64_t mmio_hole_size;
-
-            b_info->u.hvm.mmio_hole_memkb = l * 1024;
-            mmio_hole_size = b_info->u.hvm.mmio_hole_memkb * 1024;
-            if (mmio_hole_size < HVM_BELOW_4G_MMIO_LENGTH ||
-                mmio_hole_size > HVM_BELOW_4G_MMIO_START) {
-                fprintf(stderr,
-                        "ERROR: invalid value %ld for \"mmio_hole\"\n", l);
-                exit (1);
-            }
-        }
-        if (!xlu_cfg_get_long(config, "timer_mode", &l, 1)) {
-            const char *s = libxl_timer_mode_to_string(l);
-            fprintf(stderr, "WARNING: specifying \"timer_mode\" as an integer is deprecated. "
-                    "Please use the named parameter variant. %s%s%s\n",
-                    s ? "e.g. timer_mode=\"" : "",
-                    s ? s : "",
-                    s ? "\"" : "");
-
-            if (l < LIBXL_TIMER_MODE_DELAY_FOR_MISSED_TICKS ||
-                l > LIBXL_TIMER_MODE_ONE_MISSED_TICK_PENDING) {
-                fprintf(stderr, "ERROR: invalid value %ld for \"timer_mode\"\n", l);
-                exit (1);
-            }
-            b_info->u.hvm.timer_mode = l;
-        } else if (!xlu_cfg_get_string(config, "timer_mode", &buf, 0)) {
-            if (libxl_timer_mode_from_string(buf, &b_info->u.hvm.timer_mode)) {
-                fprintf(stderr, "ERROR: invalid value \"%s\" for \"timer_mode\"\n",
-                        buf);
-                exit (1);
-            }
-        }
-
-        xlu_cfg_get_defbool(config, "nestedhvm", &b_info->u.hvm.nested_hvm, 0);
-
-        xlu_cfg_get_defbool(config, "altp2mhvm", &b_info->u.hvm.altp2m, 0);
-
-        xlu_cfg_replace_string(config, "smbios_firmware",
-                               &b_info->u.hvm.smbios_firmware, 0);
-        xlu_cfg_replace_string(config, "acpi_firmware",
-                               &b_info->u.hvm.acpi_firmware, 0);
-
-        if (!xlu_cfg_get_string(config, "ms_vm_genid", &buf, 0)) {
-            if (!strcmp(buf, "generate")) {
-                e = libxl_ms_vm_genid_generate(ctx, &b_info->u.hvm.ms_vm_genid);
-                if (e) {
-                    fprintf(stderr, "ERROR: failed to generate a VM Generation ID\n");
-                    exit(1);
-                }
-            } else if (!strcmp(buf, "none")) {
-                ;
-            } else {
-                    fprintf(stderr, "ERROR: \"ms_vm_genid\" option must be \"generate\" or \"none\"\n");
-                    exit(1);
-            }
-        }
-
-        if (!xlu_cfg_get_long (config, "rdm_mem_boundary", &l, 0))
-            b_info->u.hvm.rdm_mem_boundary_memkb = l * 1024;
-        break;
-    case LIBXL_DOMAIN_TYPE_PV:
-    {
-        xlu_cfg_replace_string (config, "bootloader", &b_info->u.pv.bootloader, 0);
-        switch (xlu_cfg_get_list_as_string_list(config, "bootloader_args",
-                                      &b_info->u.pv.bootloader_args, 1))
-        {
-
-        case 0: break; /* Success */
-        case ESRCH: break; /* Option not present */
-        case EINVAL:
-            if (!xlu_cfg_get_string(config, "bootloader_args", &buf, 0)) {
-
-                fprintf(stderr, "WARNING: Specifying \"bootloader_args\""
-                        " as a string is deprecated. "
-                        "Please use a list of arguments.\n");
-                split_string_into_string_list(buf, " \t\n",
-                                              &b_info->u.pv.bootloader_args);
-            }
-            break;
-        default:
-            fprintf(stderr,"xl: Unable to parse bootloader_args.\n");
-            exit(-ERROR_FAIL);
-        }
-
-        if (!b_info->u.pv.bootloader && !b_info->kernel) {
-            fprintf(stderr, "Neither kernel nor bootloader specified\n");
-            exit(1);
-        }
-
-        break;
-    }
-    default:
-        abort();
-    }
-
-    if (!xlu_cfg_get_list(config, "ioports", &ioports, &num_ioports, 0)) {
-        b_info->num_ioports = num_ioports;
-        b_info->ioports = calloc(num_ioports, sizeof(*b_info->ioports));
-        if (b_info->ioports == NULL) {
-            fprintf(stderr, "unable to allocate memory for ioports\n");
-            exit(-1);
-        }
-
-        for (i = 0; i < num_ioports; i++) {
-            const char *buf2;
-            char *ep;
-            uint32_t start, end;
-            unsigned long ul;
-
-            buf = xlu_cfg_get_listitem (ioports, i);
-            if (!buf) {
-                fprintf(stderr,
-                        "xl: Unable to get element #%d in ioport list\n", i);
-                exit(1);
-            }
-            ul = strtoul(buf, &ep, 16);
-            if (ep == buf) {
-                fprintf(stderr, "xl: Invalid argument parsing ioport: %s\n",
-                        buf);
-                exit(1);
-            }
-            if (ul >= UINT32_MAX) {
-                fprintf(stderr, "xl: ioport %lx too big\n", ul);
-                exit(1);
-            }
-            start = end = ul;
-
-            if (*ep == '-') {
-                buf2 = ep + 1;
-                ul = strtoul(buf2, &ep, 16);
-                if (ep == buf2 || *ep != '\0' || start > end) {
-                    fprintf(stderr,
-                            "xl: Invalid argument parsing ioport: %s\n", buf);
-                    exit(1);
-                }
-                if (ul >= UINT32_MAX) {
-                    fprintf(stderr, "xl: ioport %lx too big\n", ul);
-                    exit(1);
-                }
-                end = ul;
-            } else if ( *ep != '\0' )
-                fprintf(stderr,
-                        "xl: Invalid argument parsing ioport: %s\n", buf);
-            b_info->ioports[i].first = start;
-            b_info->ioports[i].number = end - start + 1;
-        }
-    }
-
-    if (!xlu_cfg_get_list(config, "irqs", &irqs, &num_irqs, 0)) {
-        b_info->num_irqs = num_irqs;
-        b_info->irqs = calloc(num_irqs, sizeof(*b_info->irqs));
-        if (b_info->irqs == NULL) {
-            fprintf(stderr, "unable to allocate memory for ioports\n");
-            exit(-1);
-        }
-        for (i = 0; i < num_irqs; i++) {
-            char *ep;
-            unsigned long ul;
-            buf = xlu_cfg_get_listitem (irqs, i);
-            if (!buf) {
-                fprintf(stderr,
-                        "xl: Unable to get element %d in irq list\n", i);
-                exit(1);
-            }
-            ul = strtoul(buf, &ep, 10);
-            if (ep == buf || *ep != '\0') {
-                fprintf(stderr,
-                        "xl: Invalid argument parsing irq: %s\n", buf);
-                exit(1);
-            }
-            if (ul >= UINT32_MAX) {
-                fprintf(stderr, "xl: irq %lx too big\n", ul);
-                exit(1);
-            }
-            b_info->irqs[i] = ul;
-        }
+        close(fd_lock);
+        fprintf(stderr, "cannot set cloexec to lockfile %s errno=%d\n", lockfile, errno);
+        return ERROR_FAIL;
     }
+get_lock:
+    rc = fcntl(fd_lock, F_SETLKW, &fl);
+    if (rc < 0 && errno == EINTR)
+        goto get_lock;
+    if (rc < 0) {
+        fprintf(stderr, "cannot acquire lock %s errno=%d\n", lockfile, errno);
+        rc = ERROR_FAIL;
+    } else
+        rc = 0;
+    return rc;
+}
 
-    if (!xlu_cfg_get_list(config, "iomem", &iomem, &num_iomem, 0)) {
-        int ret;
-        b_info->num_iomem = num_iomem;
-        b_info->iomem = calloc(num_iomem, sizeof(*b_info->iomem));
-        if (b_info->iomem == NULL) {
-            fprintf(stderr, "unable to allocate memory for iomem\n");
-            exit(-1);
-        }
-        for (i = 0; i < num_iomem; i++) {
-            int used;
+static int release_lock(void)
+{
+    int rc;
+    struct flock fl;
 
-            buf = xlu_cfg_get_listitem (iomem, i);
-            if (!buf) {
-                fprintf(stderr,
-                        "xl: Unable to get element %d in iomem list\n", i);
-                exit(1);
-            }
-            libxl_iomem_range_init(&b_info->iomem[i]);
-            ret = sscanf(buf, "%" SCNx64",%" SCNx64"%n@%" SCNx64"%n",
-                         &b_info->iomem[i].start,
-                         &b_info->iomem[i].number, &used,
-                         &b_info->iomem[i].gfn, &used);
-            if (ret < 2 || buf[used] != '\0') {
-                fprintf(stderr,
-                        "xl: Invalid argument parsing iomem: %s\n", buf);
-                exit(1);
-            }
-        }
-    }
+    /* lock not acquired */
+    if (fd_lock < 0)
+        return ERROR_INVAL;
 
+release_lock:
+    fl.l_type = F_UNLCK;
+    fl.l_whence = SEEK_SET;
+    fl.l_start = 0;
+    fl.l_len = 0;
 
+    rc = fcntl(fd_lock, F_SETLKW, &fl);
+    if (rc < 0 && errno == EINTR)
+        goto release_lock;
+    if (rc < 0) {
+        fprintf(stderr, "cannot release lock %s, errno=%d\n", lockfile, errno);
+        rc = ERROR_FAIL;
+    } else
+        rc = 0;
+    close(fd_lock);
+    fd_lock = -1;
 
-    if (!xlu_cfg_get_list (config, "disk", &vbds, 0, 0)) {
-        d_config->num_disks = 0;
-        d_config->disks = NULL;
-        while ((buf = xlu_cfg_get_listitem (vbds, d_config->num_disks)) != NULL) {
-            libxl_device_disk *disk;
-            char *buf2 = strdup(buf);
-
-            disk = ARRAY_EXTEND_INIT_NODEVID(d_config->disks,
-                                             d_config->num_disks,
-                                             libxl_device_disk_init);
-            parse_disk_config(&config, buf2, disk);
-
-            free(buf2);
-        }
-    }
-
-    if (!xlu_cfg_get_list(config, "vtpm", &vtpms, 0, 0)) {
-        d_config->num_vtpms = 0;
-        d_config->vtpms = NULL;
-        while ((buf = xlu_cfg_get_listitem (vtpms, d_config->num_vtpms)) != NULL) {
-            libxl_device_vtpm *vtpm;
-            char * buf2 = strdup(buf);
-            char *p, *p2;
-            bool got_backend = false;
-
-            vtpm = ARRAY_EXTEND_INIT(d_config->vtpms,
-                                     d_config->num_vtpms,
-                                     libxl_device_vtpm_init);
-
-            p = strtok(buf2, ",");
-            if(p) {
-               do {
-                  while(*p == ' ')
-                     ++p;
-                  if ((p2 = strchr(p, '=')) == NULL)
-                     break;
-                  *p2 = '\0';
-                  if (!strcmp(p, "backend")) {
-                     vtpm->backend_domname = strdup(p2 + 1);
-                     got_backend = true;
-                  } else if(!strcmp(p, "uuid")) {
-                     if( libxl_uuid_from_string(&vtpm->uuid, p2 + 1) ) {
-                        fprintf(stderr,
-                              "Failed to parse vtpm UUID: %s\n", p2 + 1);
-                        exit(1);
-                    }
-                  } else {
-                     fprintf(stderr, "Unknown string `%s' in vtpm spec\n", p);
-                     exit(1);
-                  }
-               } while ((p = strtok(NULL, ",")) != NULL);
-            }
-            if(!got_backend) {
-               fprintf(stderr, "vtpm spec missing required backend field!\n");
-               exit(1);
-            }
-            free(buf2);
-        }
-    }
-
-    if (!xlu_cfg_get_list (config, "channel", &channels, 0, 0)) {
-        d_config->num_channels = 0;
-        d_config->channels = NULL;
-        while ((buf = xlu_cfg_get_listitem (channels,
-                d_config->num_channels)) != NULL) {
-            libxl_device_channel *chn;
-            libxl_string_list pairs;
-            char *path = NULL;
-            int len;
-
-            chn = ARRAY_EXTEND_INIT(d_config->channels, d_config->num_channels,
-                                   libxl_device_channel_init);
-
-            split_string_into_string_list(buf, ",", &pairs);
-            len = libxl_string_list_length(&pairs);
-            for (i = 0; i < len; i++) {
-                char *key, *key_untrimmed, *value, *value_untrimmed;
-                int rc;
-                rc = split_string_into_pair(pairs[i], "=",
-                                            &key_untrimmed,
-                                            &value_untrimmed);
-                if (rc != 0) {
-                    fprintf(stderr, "failed to parse channel configuration: %s",
-                            pairs[i]);
-                    exit(1);
-                }
-                trim(isspace, key_untrimmed, &key);
-                trim(isspace, value_untrimmed, &value);
-
-                if (!strcmp(key, "backend")) {
-                    replace_string(&chn->backend_domname, value);
-                } else if (!strcmp(key, "name")) {
-                    replace_string(&chn->name, value);
-                } else if (!strcmp(key, "path")) {
-                    replace_string(&path, value);
-                } else if (!strcmp(key, "connection")) {
-                    if (!strcmp(value, "pty")) {
-                        chn->connection = LIBXL_CHANNEL_CONNECTION_PTY;
-                    } else if (!strcmp(value, "socket")) {
-                        chn->connection = LIBXL_CHANNEL_CONNECTION_SOCKET;
-                    } else {
-                        fprintf(stderr, "unknown channel connection '%s'\n",
-                                value);
-                        exit(1);
-                    }
-                } else {
-                    fprintf(stderr, "unknown channel parameter '%s',"
-                                  " ignoring\n", key);
-                }
-                free(key);
-                free(key_untrimmed);
-                free(value);
-                free(value_untrimmed);
-            }
-            switch (chn->connection) {
-            case LIBXL_CHANNEL_CONNECTION_UNKNOWN:
-                fprintf(stderr, "channel has unknown 'connection'\n");
-                exit(1);
-            case LIBXL_CHANNEL_CONNECTION_SOCKET:
-                if (!path) {
-                    fprintf(stderr, "channel connection 'socket' requires path=..\n");
-                    exit(1);
-                }
-                chn->u.socket.path = xstrdup(path);
-                break;
-            case LIBXL_CHANNEL_CONNECTION_PTY:
-                /* Nothing to do since PTY has no arguments */
-                break;
-            default:
-                fprintf(stderr, "unknown channel connection: %d",
-                        chn->connection);
-                exit(1);
-            }
-            libxl_string_list_dispose(&pairs);
-            free(path);
-        }
-    }
-
-    if (!xlu_cfg_get_list (config, "vif", &nics, 0, 0)) {
-        d_config->num_nics = 0;
-        d_config->nics = NULL;
-        while ((buf = xlu_cfg_get_listitem (nics, d_config->num_nics)) != NULL) {
-            libxl_device_nic *nic;
-            char *buf2 = strdup(buf);
-            char *p;
-
-            nic = ARRAY_EXTEND_INIT(d_config->nics,
-                                    d_config->num_nics,
-                                    libxl_device_nic_init);
-            set_default_nic_values(nic);
-
-            p = strtok(buf2, ",");
-            if (!p)
-                goto skip_nic;
-            do {
-                while (*p == ' ')
-                    p++;
-                parse_nic_config(nic, &config, p);
-            } while ((p = strtok(NULL, ",")) != NULL);
-skip_nic:
-            free(buf2);
-        }
-    }
-
-    if (!xlu_cfg_get_list(config, "vif2", NULL, 0, 0)) {
-        fprintf(stderr, "WARNING: vif2: netchannel2 is deprecated and not supported by xl\n");
-    }
-
-    d_config->num_vfbs = 0;
-    d_config->num_vkbs = 0;
-    d_config->vfbs = NULL;
-    d_config->vkbs = NULL;
-
-    if (!xlu_cfg_get_list (config, "vfb", &cvfbs, 0, 0)) {
-        while ((buf = xlu_cfg_get_listitem (cvfbs, d_config->num_vfbs)) != NULL) {
-            libxl_device_vfb *vfb;
-            libxl_device_vkb *vkb;
-
-            char *buf2 = strdup(buf);
-            char *p, *p2;
-
-            vfb = ARRAY_EXTEND_INIT(d_config->vfbs, d_config->num_vfbs,
-                                    libxl_device_vfb_init);
-
-            vkb = ARRAY_EXTEND_INIT(d_config->vkbs, d_config->num_vkbs,
-                                    libxl_device_vkb_init);
-
-            p = strtok(buf2, ",");
-            if (!p)
-                goto skip_vfb;
-            do {
-                while (*p == ' ')
-                    p++;
-                if ((p2 = strchr(p, '=')) == NULL)
-                    break;
-                *p2 = '\0';
-                if (!strcmp(p, "vnc")) {
-                    libxl_defbool_set(&vfb->vnc.enable, atoi(p2 + 1));
-                } else if (!strcmp(p, "vnclisten")) {
-                    free(vfb->vnc.listen);
-                    vfb->vnc.listen = strdup(p2 + 1);
-                } else if (!strcmp(p, "vncpasswd")) {
-                    free(vfb->vnc.passwd);
-                    vfb->vnc.passwd = strdup(p2 + 1);
-                } else if (!strcmp(p, "vncdisplay")) {
-                    vfb->vnc.display = atoi(p2 + 1);
-                } else if (!strcmp(p, "vncunused")) {
-                    libxl_defbool_set(&vfb->vnc.findunused, atoi(p2 + 1));
-                } else if (!strcmp(p, "keymap")) {
-                    free(vfb->keymap);
-                    vfb->keymap = strdup(p2 + 1);
-                } else if (!strcmp(p, "sdl")) {
-                    libxl_defbool_set(&vfb->sdl.enable, atoi(p2 + 1));
-                } else if (!strcmp(p, "opengl")) {
-                    libxl_defbool_set(&vfb->sdl.opengl, atoi(p2 + 1));
-                } else if (!strcmp(p, "display")) {
-                    free(vfb->sdl.display);
-                    vfb->sdl.display = strdup(p2 + 1);
-                } else if (!strcmp(p, "xauthority")) {
-                    free(vfb->sdl.xauthority);
-                    vfb->sdl.xauthority = strdup(p2 + 1);
-                }
-            } while ((p = strtok(NULL, ",")) != NULL);
+    return rc;
+}
 
-skip_vfb:
-            free(buf2);
-        }
-    }
+static yajl_gen_status printf_info_one_json(yajl_gen hand, int domid,
+                                            libxl_domain_config *d_config)
+{
+    yajl_gen_status s;
 
-    if (!xlu_cfg_get_long (config, "pci_msitranslate", &l, 0))
-        pci_msitranslate = l;
+    s = yajl_gen_map_open(hand);
+    if (s != yajl_gen_status_ok)
+        goto out;
 
-    if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l, 0))
-        pci_power_mgmt = l;
+    s = yajl_gen_string(hand, (const unsigned char *)"domid",
+                        sizeof("domid")-1);
+    if (s != yajl_gen_status_ok)
+        goto out;
+    if (domid != -1)
+        s = yajl_gen_integer(hand, domid);
+    else
+        s = yajl_gen_null(hand);
+    if (s != yajl_gen_status_ok)
+        goto out;
 
-    if (!xlu_cfg_get_long (config, "pci_permissive", &l, 0))
-        pci_permissive = l;
+    s = yajl_gen_string(hand, (const unsigned char *)"config",
+                        sizeof("config")-1);
+    if (s != yajl_gen_status_ok)
+        goto out;
+    s = libxl_domain_config_gen_json(hand, d_config);
+    if (s != yajl_gen_status_ok)
+        goto out;
 
-    if (!xlu_cfg_get_long (config, "pci_seize", &l, 0))
-        pci_seize = l;
+    s = yajl_gen_map_close(hand);
+    if (s != yajl_gen_status_ok)
+        goto out;
 
-    /* To be reworked (automatically enabled) once the auto ballooning
-     * after guest starts is done (with PCI devices passed in). */
-    if (c_info->type == LIBXL_DOMAIN_TYPE_PV) {
-        xlu_cfg_get_defbool(config, "e820_host", &b_info->u.pv.e820_host, 0);
-    }
+out:
+    return s;
+}
 
-    if (!xlu_cfg_get_string(config, "rdm", &buf, 0)) {
-        libxl_rdm_reserve rdm;
-        if (!xlu_rdm_parse(config, &rdm, buf)) {
-            b_info->u.hvm.rdm.strategy = rdm.strategy;
-            b_info->u.hvm.rdm.policy = rdm.policy;
-        }
-    }
+static void printf_info(enum output_format output_format,
+                        int domid,
+                        libxl_domain_config *d_config, FILE *fh)
+{
+    if (output_format == OUTPUT_FORMAT_SXP)
+        return printf_info_sexp(domid, d_config, fh);
 
-    if (!xlu_cfg_get_list (config, "pci", &pcis, 0, 0)) {
-        d_config->num_pcidevs = 0;
-        d_config->pcidevs = NULL;
-        for(i = 0; (buf = xlu_cfg_get_listitem (pcis, i)) != NULL; i++) {
-            libxl_device_pci *pcidev;
+    const char *buf;
+    libxl_yajl_length len = 0;
+    yajl_gen_status s;
+    yajl_gen hand;
 
-            pcidev = ARRAY_EXTEND_INIT_NODEVID(d_config->pcidevs,
-                                               d_config->num_pcidevs,
-                                               libxl_device_pci_init);
-            pcidev->msitranslate = pci_msitranslate;
-            pcidev->power_mgmt = pci_power_mgmt;
-            pcidev->permissive = pci_permissive;
-            pcidev->seize = pci_seize;
-            /*
-             * Like other pci option, the per-device policy always follows
-             * the global policy by default.
-             */
-            pcidev->rdm_policy = b_info->u.hvm.rdm.policy;
-            e = xlu_pci_parse_bdf(config, pcidev, buf);
-            if (e) {
-                fprintf(stderr,
-                        "unable to parse PCI BDF `%s' for passthrough\n",
-                        buf);
-                exit(-e);
-            }
-        }
-        if (d_config->num_pcidevs && c_info->type == LIBXL_DOMAIN_TYPE_PV)
-            libxl_defbool_set(&b_info->u.pv.e820_host, true);
+    hand = libxl_yajl_gen_alloc(NULL);
+    if (!hand) {
+        fprintf(stderr, "unable to allocate JSON generator\n");
+        return;
     }
 
-    if (!xlu_cfg_get_list (config, "dtdev", &dtdevs, 0, 0)) {
-        d_config->num_dtdevs = 0;
-        d_config->dtdevs = NULL;
-        for (i = 0; (buf = xlu_cfg_get_listitem(dtdevs, i)) != NULL; i++) {
-            libxl_device_dtdev *dtdev;
+    s = printf_info_one_json(hand, domid, d_config);
+    if (s != yajl_gen_status_ok)
+        goto out;
 
-            dtdev = ARRAY_EXTEND_INIT_NODEVID(d_config->dtdevs,
-                                              d_config->num_dtdevs,
-                                              libxl_device_dtdev_init);
+    s = yajl_gen_get_buf(hand, (const unsigned char **)&buf, &len);
+    if (s != yajl_gen_status_ok)
+        goto out;
 
-            dtdev->path = strdup(buf);
-            if (dtdev->path == NULL) {
-                fprintf(stderr, "unable to duplicate string for dtdevs\n");
-                exit(-1);
-            }
-        }
-    }
+    fputs(buf, fh);
 
-    if (!xlu_cfg_get_list(config, "usbctrl", &usbctrls, 0, 0)) {
-        d_config->num_usbctrls = 0;
-        d_config->usbctrls = NULL;
-        while ((buf = xlu_cfg_get_listitem(usbctrls, d_config->num_usbctrls))
-               != NULL) {
-            libxl_device_usbctrl *usbctrl;
-            char *buf2 = strdup(buf);
-            char *p;
-
-            usbctrl = ARRAY_EXTEND_INIT(d_config->usbctrls,
-                                        d_config->num_usbctrls,
-                                        libxl_device_usbctrl_init);
-            p = strtok(buf2, ",");
-            if (!p)
-                goto skip_usbctrl;
-            do {
-                while (*p == ' ')
-                    p++;
-                if (parse_usbctrl_config(usbctrl, p))
-                    exit(1);
-            } while ((p = strtok(NULL, ",")) != NULL);
-skip_usbctrl:
-            free(buf2);
-        }
-    }
-
-    if (!xlu_cfg_get_list(config, "usbdev", &usbdevs, 0, 0)) {
-        d_config->num_usbdevs = 0;
-        d_config->usbdevs = NULL;
-        while ((buf = xlu_cfg_get_listitem(usbdevs, d_config->num_usbdevs))
-               != NULL) {
-            libxl_device_usbdev *usbdev;
-            char *buf2 = strdup(buf);
-            char *p;
-
-            usbdev = ARRAY_EXTEND_INIT_NODEVID(d_config->usbdevs,
-                                               d_config->num_usbdevs,
-                                               libxl_device_usbdev_init);
-            p = strtok(buf2, ",");
-            if (!p)
-                goto skip_usbdev;
-            do {
-                while (*p == ' ')
-                    p++;
-                if (parse_usbdev_config(usbdev, p))
-                    exit(1);
-            } while ((p = strtok(NULL, ",")) != NULL);
-skip_usbdev:
-            free(buf2);
-        }
-    }
-
-    switch (xlu_cfg_get_list(config, "cpuid", &cpuids, 0, 1)) {
-    case 0:
-        {
-            const char *errstr;
-
-            for (i = 0; (buf = xlu_cfg_get_listitem(cpuids, i)) != NULL; i++) {
-                e = libxl_cpuid_parse_config_xend(&b_info->cpuid, buf);
-                switch (e) {
-                case 0: continue;
-                case 1:
-                    errstr = "illegal leaf number";
-                    break;
-                case 2:
-                    errstr = "illegal subleaf number";
-                    break;
-                case 3:
-                    errstr = "missing colon";
-                    break;
-                case 4:
-                    errstr = "invalid register name (must be e[abcd]x)";
-                    break;
-                case 5:
-                    errstr = "policy string must be exactly 32 characters long";
-                    break;
-                default:
-                    errstr = "unknown error";
-                    break;
-                }
-                fprintf(stderr, "while parsing CPUID line: \"%s\":\n", buf);
-                fprintf(stderr, "  error #%i: %s\n", e, errstr);
-            }
-        }
-        break;
-    case EINVAL:    /* config option is not a list, parse as a string */
-        if (!xlu_cfg_get_string(config, "cpuid", &buf, 0)) {
-            char *buf2, *p, *strtok_ptr = NULL;
-            const char *errstr;
-
-            buf2 = strdup(buf);
-            p = strtok_r(buf2, ",", &strtok_ptr);
-            if (p == NULL) {
-                free(buf2);
-                break;
-            }
-            if (strcmp(p, "host")) {
-                fprintf(stderr, "while parsing CPUID string: \"%s\":\n", buf);
-                fprintf(stderr, "  error: first word must be \"host\"\n");
-                free(buf2);
-                break;
-            }
-            for (p = strtok_r(NULL, ",", &strtok_ptr); p != NULL;
-                 p = strtok_r(NULL, ",", &strtok_ptr)) {
-                e = libxl_cpuid_parse_config(&b_info->cpuid, p);
-                switch (e) {
-                case 0: continue;
-                case 1:
-                    errstr = "missing \"=\" in key=value";
-                    break;
-                case 2:
-                    errstr = "unknown CPUID flag name";
-                    break;
-                case 3:
-                    errstr = "illegal CPUID value (must be: [0|1|x|k|s])";
-                    break;
-                default:
-                    errstr = "unknown error";
-                    break;
-                }
-                fprintf(stderr, "while parsing CPUID flag: \"%s\":\n", p);
-                fprintf(stderr, "  error #%i: %s\n", e, errstr);
-            }
-            free(buf2);
-        }
-        break;
-    default:
-        break;
-    }
+out:
+    yajl_gen_free(hand);
 
-    /* parse device model arguments, this works for pv, hvm and stubdom */
-    if (!xlu_cfg_get_string (config, "device_model", &buf, 0)) {
+    if (s != yajl_gen_status_ok)
         fprintf(stderr,
-                "WARNING: ignoring device_model directive.\n"
-                "WARNING: Use \"device_model_override\" instead if you"
-                " really want a non-default device_model\n");
-        if (strstr(buf, "stubdom-dm")) {
-            if (c_info->type == LIBXL_DOMAIN_TYPE_HVM)
-                fprintf(stderr, "WARNING: Or use"
-                        " \"device_model_stubdomain_override\" if you "
-                        " want to enable stubdomains\n");
-            else
-                fprintf(stderr, "WARNING: ignoring"
-                        " \"device_model_stubdomain_override\" directive"
-                        " for pv guest\n");
-        }
-    }
+                "unable to format domain config as JSON (YAJL:%d)\n", s);
 
+    flush_stream(fh);
+}
 
-    xlu_cfg_replace_string (config, "device_model_override",
-                            &b_info->device_model, 0);
-    if (!xlu_cfg_get_string (config, "device_model_version", &buf, 0)) {
-        if (!strcmp(buf, "qemu-xen-traditional")) {
-            b_info->device_model_version
-                = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL;
-        } else if (!strcmp(buf, "qemu-xen")) {
-            b_info->device_model_version
-                = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN;
-        } else if (!strcmp(buf, "none")) {
-            b_info->device_model_version = LIBXL_DEVICE_MODEL_VERSION_NONE;
-        } else {
-            fprintf(stderr,
-                    "Unknown device_model_version \"%s\" specified\n", buf);
-            exit(1);
-        }
-    } else if (b_info->device_model)
-        fprintf(stderr, "WARNING: device model override given without specific DM version\n");
-    xlu_cfg_get_defbool (config, "device_model_stubdomain_override",
-                         &b_info->device_model_stubdomain, 0);
+static int do_daemonize(char *name, const char *pidfile)
+{
+    char *fullname;
+    pid_t child1;
+    int nullfd, ret = 0;
 
-    if (!xlu_cfg_get_string (config, "device_model_stubdomain_seclabel",
-                             &buf, 0))
-        xlu_cfg_replace_string(config, "device_model_stubdomain_seclabel",
-                               &b_info->device_model_ssid_label, 0);
+    child1 = xl_fork(child_waitdaemon, "domain monitoring daemonizing child");
+    if (child1) {
+        ret = child_report(child_waitdaemon);
+        if (ret) goto out;
+        ret = 1;
+        goto out;
+    }
 
-    xlu_cfg_replace_string(config, "device_model_user",
-                           &b_info->device_model_user, 0);
+    postfork();
 
-#define parse_extra_args(type)                                            \
-    e = xlu_cfg_get_list_as_string_list(config, "device_model_args"#type, \
-                                    &b_info->extra##type, 0);            \
-    if (e && e != ESRCH) {                                                \
-        fprintf(stderr,"xl: Unable to parse device_model_args"#type".\n");\
-        exit(-ERROR_FAIL);                                                \
+    ret = libxl_create_logfile(ctx, name, &fullname);
+    if (ret) {
+        LOG("failed to open logfile %s: %s",fullname,strerror(errno));
+        exit(-1);
     }
 
-    /* parse extra args for qemu, common to both pv, hvm */
-    parse_extra_args();
-
-    /* parse extra args dedicated to pv */
-    parse_extra_args(_pv);
+    CHK_SYSCALL(logfile = open(fullname, O_WRONLY|O_CREAT|O_APPEND, 0644));
+    free(fullname);
+    assert(logfile >= 3);
 
-    /* parse extra args dedicated to hvm */
-    parse_extra_args(_hvm);
+    CHK_SYSCALL(nullfd = open("/dev/null", O_RDONLY));
+    assert(nullfd >= 3);
 
-#undef parse_extra_args
+    dup2(nullfd, 0);
+    dup2(logfile, 1);
+    dup2(logfile, 2);
 
-    /* If we've already got vfb=[] for PV guest then ignore top level
-     * VNC config. */
-    if (c_info->type == LIBXL_DOMAIN_TYPE_PV && !d_config->num_vfbs) {
-        long vnc_enabled = 0;
+    close(nullfd);
 
-        if (!xlu_cfg_get_long (config, "vnc", &l, 0))
-            vnc_enabled = l;
+    CHK_SYSCALL(daemon(0, 1));
 
-        if (vnc_enabled) {
-            libxl_device_vfb *vfb;
-            libxl_device_vkb *vkb;
+    if (pidfile) {
+        int fd = open(pidfile, O_RDWR | O_CREAT, S_IRUSR|S_IWUSR);
+        char *pid = NULL;
 
-            vfb = ARRAY_EXTEND_INIT(d_config->vfbs, d_config->num_vfbs,
-                                    libxl_device_vfb_init);
+        if (fd == -1) {
+            perror("Unable to open pidfile");
+            exit(1);
+        }
 
-            vkb = ARRAY_EXTEND_INIT(d_config->vkbs, d_config->num_vkbs,
-                                    libxl_device_vkb_init);
+        if (asprintf(&pid, "%ld\n", (long)getpid()) == -1) {
+            perror("Formatting pid");
+            exit(1);
+        }
 
-            parse_top_level_vnc_options(config, &vfb->vnc);
-            parse_top_level_sdl_options(config, &vfb->sdl);
-            xlu_cfg_replace_string (config, "keymap", &vfb->keymap, 0);
+        if (write(fd, pid, strlen(pid)) < 0) {
+            perror("Writing pid");
+            exit(1);
         }
-    } else {
-        parse_top_level_vnc_options(config, &b_info->u.hvm.vnc);
-        parse_top_level_sdl_options(config, &b_info->u.hvm.sdl);
-    }
-
-    if (c_info->type == LIBXL_DOMAIN_TYPE_HVM) {
-        if (!xlu_cfg_get_string (config, "vga", &buf, 0)) {
-            if (!strcmp(buf, "stdvga")) {
-                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_STD;
-            } else if (!strcmp(buf, "cirrus")) {
-                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
-            } else if (!strcmp(buf, "none")) {
-                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_NONE;
-            } else if (!strcmp(buf, "qxl")) {
-                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_QXL;
-            } else {
-                fprintf(stderr, "Unknown vga \"%s\" specified\n", buf);
-                exit(1);
-            }
-        } else if (!xlu_cfg_get_long(config, "stdvga", &l, 0))
-            b_info->u.hvm.vga.kind = l ? LIBXL_VGA_INTERFACE_TYPE_STD :
-                                         LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
-
-        if (!xlu_cfg_get_string(config, "hdtype", &buf, 0) &&
-            libxl_hdtype_from_string(buf, &b_info->u.hvm.hdtype)) {
-                fprintf(stderr, "ERROR: invalid value \"%s\" for \"hdtype\"\n",
-                    buf);
-                exit (1);
-        }
-
-        xlu_cfg_replace_string (config, "keymap", &b_info->u.hvm.keymap, 0);
-        xlu_cfg_get_defbool (config, "spice", &b_info->u.hvm.spice.enable, 0);
-        if (!xlu_cfg_get_long (config, "spiceport", &l, 0))
-            b_info->u.hvm.spice.port = l;
-        if (!xlu_cfg_get_long (config, "spicetls_port", &l, 0))
-            b_info->u.hvm.spice.tls_port = l;
-        xlu_cfg_replace_string (config, "spicehost",
-                                &b_info->u.hvm.spice.host, 0);
-        xlu_cfg_get_defbool(config, "spicedisable_ticketing",
-                            &b_info->u.hvm.spice.disable_ticketing, 0);
-        xlu_cfg_replace_string (config, "spicepasswd",
-                                &b_info->u.hvm.spice.passwd, 0);
-        xlu_cfg_get_defbool(config, "spiceagent_mouse",
-                            &b_info->u.hvm.spice.agent_mouse, 0);
-        xlu_cfg_get_defbool(config, "spicevdagent",
-                            &b_info->u.hvm.spice.vdagent, 0);
-        xlu_cfg_get_defbool(config, "spice_clipboard_sharing",
-                            &b_info->u.hvm.spice.clipboard_sharing, 0);
-        if (!xlu_cfg_get_long (config, "spiceusbredirection", &l, 0))
-            b_info->u.hvm.spice.usbredirection = l;
-        xlu_cfg_replace_string (config, "spice_image_compression",
-                                &b_info->u.hvm.spice.image_compression, 0);
-        xlu_cfg_replace_string (config, "spice_streaming_video",
-                                &b_info->u.hvm.spice.streaming_video, 0);
-        xlu_cfg_get_defbool(config, "nographic", &b_info->u.hvm.nographic, 0);
-        if (!xlu_cfg_get_long(config, "gfx_passthru", &l, 1)) {
-            libxl_defbool_set(&b_info->u.hvm.gfx_passthru, l);
-        } else if (!xlu_cfg_get_string(config, "gfx_passthru", &buf, 0)) {
-            if (libxl_gfx_passthru_kind_from_string(buf,
-                                        &b_info->u.hvm.gfx_passthru_kind)) {
-                fprintf(stderr,
-                        "ERROR: invalid value \"%s\" for \"gfx_passthru\"\n",
-                        buf);
-                exit (1);
-            }
-            libxl_defbool_set(&b_info->u.hvm.gfx_passthru, true);
-        }
-        switch (xlu_cfg_get_list_as_string_list(config, "serial",
-                                                &b_info->u.hvm.serial_list,
-                                                1))
-        {
-
-        case 0: break; /* Success */
-        case ESRCH: break; /* Option not present */
-        case EINVAL:
-            /* If it's not a valid list, try reading it as an atom,
-             * falling through to an error if it fails */
-            if (!xlu_cfg_replace_string(config, "serial",
-                                        &b_info->u.hvm.serial, 0))
-                break;
-            /* FALLTHRU */
-        default:
-            fprintf(stderr,"xl: Unable to parse serial.\n");
-            exit(-ERROR_FAIL);
-        }
-        xlu_cfg_replace_string (config, "boot", &b_info->u.hvm.boot, 0);
-        xlu_cfg_get_defbool(config, "usb", &b_info->u.hvm.usb, 0);
-        if (!xlu_cfg_get_long (config, "usbversion", &l, 0))
-            b_info->u.hvm.usbversion = l;
-        switch (xlu_cfg_get_list_as_string_list(config, "usbdevice",
-                                                &b_info->u.hvm.usbdevice_list,
-                                                1))
-        {
-
-        case 0: break; /* Success */
-        case ESRCH: break; /* Option not present */
-        case EINVAL:
-            /* If it's not a valid list, try reading it as an atom,
-             * falling through to an error if it fails */
-            if (!xlu_cfg_replace_string(config, "usbdevice",
-                                        &b_info->u.hvm.usbdevice, 0))
-                break;
-            /* FALLTHRU */
-        default:
-            fprintf(stderr,"xl: Unable to parse usbdevice.\n");
-            exit(-ERROR_FAIL);
+
+        if (close(fd) < 0) {
+            perror("Closing pidfile");
+            exit(1);
         }
-        xlu_cfg_replace_string (config, "soundhw", &b_info->u.hvm.soundhw, 0);
-        xlu_cfg_get_defbool(config, "xen_platform_pci",
-                            &b_info->u.hvm.xen_platform_pci, 0);
 
-        if(b_info->u.hvm.vnc.listen
-           && b_info->u.hvm.vnc.display
-           && strchr(b_info->u.hvm.vnc.listen, ':') != NULL) {
-            fprintf(stderr,
-                    "ERROR: Display specified both in vnclisten"
-                    " and vncdisplay!\n");
-            exit (1);
+        free(pid);
+    }
 
-        }
+out:
+    return ret;
+}
 
-        if (!xlu_cfg_get_string (config, "vendor_device", &buf, 0)) {
-            libxl_vendor_device d;
+void set_default_nic_values(libxl_device_nic *nic);
+void set_default_nic_values(libxl_device_nic *nic)
+{
 
-            e = libxl_vendor_device_from_string(buf, &d);
-            if (e) {
-                fprintf(stderr,
-                        "xl: unknown vendor_device '%s'\n",
-                        buf);
-                exit(-ERROR_FAIL);
-            }
+    if (default_vifscript) {
+        free(nic->script);
+        nic->script = strdup(default_vifscript);
+    }
 
-            b_info->u.hvm.vendor_device = d;
-        }
+    if (default_bridge) {
+        free(nic->bridge);
+        nic->bridge = strdup(default_bridge);
     }
 
-    if (!xlu_cfg_get_string (config, "gic_version", &buf, 1)) {
-        e = libxl_gic_version_from_string(buf, &b_info->arch_arm.gic_version);
-        if (e) {
-            fprintf(stderr,
-                    "Unknown gic_version \"%s\" specified\n", buf);
-            exit(-ERROR_FAIL);
-        }
-     }
+    if (default_gatewaydev) {
+        free(nic->gatewaydev);
+        nic->gatewaydev = strdup(default_gatewaydev);
+    }
 
-    xlu_cfg_destroy(config);
+    if (default_vifbackend) {
+        free(nic->backend_domname);
+        nic->backend_domname = strdup(default_vifbackend);
+    }
 }
 
 static void reload_domain_config(uint32_t domid,
@@ -3154,40 +1170,6 @@ void help(const char *command)
     }
 }
 
-/* Returns -1 on failure; the amount of memory on success. */
-static int64_t parse_mem_size_kb(const char *mem)
-{
-    char *endptr;
-    int64_t kbytes;
-
-    kbytes = strtoll(mem, &endptr, 10);
-
-    if (strlen(endptr) > 1)
-        return -1;
-
-    switch (tolower((uint8_t)*endptr)) {
-    case 't':
-        kbytes <<= 10;
-        /* fallthrough */
-    case 'g':
-        kbytes <<= 10;
-        /* fallthrough */
-    case '\0':
-    case 'm':
-        kbytes <<= 10;
-        /* fallthrough */
-    case 'k':
-        break;
-    case 'b':
-        kbytes >>= 10;
-        break;
-    default:
-        return -1;
-    }
-
-    return kbytes;
-}
-
 static int set_memory_max(uint32_t domid, const char *mem)
 {
     int64_t memorykb;
diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
new file mode 100644
index 0000000000..1ef0c272a8
--- /dev/null
+++ b/tools/xl/xl_parse.c
@@ -0,0 +1,2052 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <ctype.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <xen/hvm/e820.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+extern void set_default_nic_values(libxl_device_nic *nic);
+
+#define ARRAY_EXTEND_INIT__CORE(array,count,initfn,more)                \
+    ({                                                                  \
+        typeof((count)) array_extend_old_count = (count);               \
+        (count)++;                                                      \
+        (array) = xrealloc((array), sizeof(*array) * (count));          \
+        (initfn)(&(array)[array_extend_old_count]);                     \
+        more;                                                           \
+        &(array)[array_extend_old_count];                               \
+    })
+
+#define ARRAY_EXTEND_INIT(array,count,initfn)                           \
+    ARRAY_EXTEND_INIT__CORE((array),(count),(initfn), ({                \
+        (array)[array_extend_old_count].devid = array_extend_old_count; \
+        }))
+
+#define ARRAY_EXTEND_INIT_NODEVID(array,count,initfn) \
+    ARRAY_EXTEND_INIT__CORE((array),(count),(initfn), /* nothing */ )
+
+static const char *action_on_shutdown_names[] = {
+    [LIBXL_ACTION_ON_SHUTDOWN_DESTROY] = "destroy",
+
+    [LIBXL_ACTION_ON_SHUTDOWN_RESTART] = "restart",
+    [LIBXL_ACTION_ON_SHUTDOWN_RESTART_RENAME] = "rename-restart",
+
+    [LIBXL_ACTION_ON_SHUTDOWN_PRESERVE] = "preserve",
+
+    [LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY] = "coredump-destroy",
+    [LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_RESTART] = "coredump-restart",
+
+    [LIBXL_ACTION_ON_SHUTDOWN_SOFT_RESET] = "soft-reset",
+};
+
+const char *get_action_on_shutdown_name(libxl_action_on_shutdown a)
+{
+    return action_on_shutdown_names[a];
+}
+
+static int parse_action_on_shutdown(const char *buf, libxl_action_on_shutdown *a)
+{
+    int i;
+    const char *n;
+
+    for (i = 0; i < sizeof(action_on_shutdown_names) / sizeof(action_on_shutdown_names[0]); i++) {
+        n = action_on_shutdown_names[i];
+
+        if (!n) continue;
+
+        if (strcmp(buf, n) == 0) {
+            *a = i;
+            return 1;
+        }
+    }
+    return 0;
+}
+
+#define DSTATE_INITIAL   0
+#define DSTATE_TAP       1
+#define DSTATE_PHYSPATH  2
+#define DSTATE_VIRTPATH  3
+#define DSTATE_VIRTTYPE  4
+#define DSTATE_RW        5
+#define DSTATE_TERMINAL  6
+
+void parse_disk_config_multistring(XLU_Config **config,
+                                   int nspecs, const char *const *specs,
+                                   libxl_device_disk *disk)
+{
+    int e;
+
+    libxl_device_disk_init(disk);
+
+    if (!*config) {
+        *config = xlu_cfg_init(stderr, "command line");
+        if (!*config) { perror("xlu_cfg_init"); exit(-1); }
+    }
+
+    e = xlu_disk_parse(*config, nspecs, specs, disk);
+    if (e == EINVAL) exit(EXIT_FAILURE);
+    if (e) {
+        fprintf(stderr,"xlu_disk_parse failed: %s\n",strerror(errno));
+        exit(EXIT_FAILURE);
+    }
+}
+
+void parse_disk_config(XLU_Config **config, const char *spec,
+                       libxl_device_disk *disk)
+{
+    parse_disk_config_multistring(config, 1, &spec, disk);
+}
+
+static void parse_vif_rate(XLU_Config **config, const char *rate,
+                           libxl_device_nic *nic)
+{
+    int e;
+
+    e = xlu_vif_parse_rate(*config, rate, nic);
+    if (e == EINVAL || e == EOVERFLOW) exit(EXIT_FAILURE);
+    if (e) {
+        fprintf(stderr,"xlu_vif_parse_rate failed: %s\n",strerror(errno));
+        exit(EXIT_FAILURE);
+    }
+}
+
+int parse_range(const char *str, unsigned long *a, unsigned long *b)
+{
+    const char *nstr;
+    char *endptr;
+
+    *a = *b = strtoul(str, &endptr, 10);
+    if (endptr == str || *a == ULONG_MAX)
+        return 1;
+
+    if (*endptr == '-') {
+        nstr = endptr + 1;
+
+        *b = strtoul(nstr, &endptr, 10);
+        if (endptr == nstr || *b == ULONG_MAX || *b < *a)
+            return 1;
+    }
+
+    /* Valid value or range so far, but we also don't want junk after that */
+    if (*endptr != '\0')
+        return 1;
+
+    return 0;
+}
+
+/*
+ * Add or removes a specific set of cpus (specified in str, either as
+ * single cpus or as entire NUMA nodes) to/from cpumap.
+ */
+static int update_cpumap_range(const char *str, libxl_bitmap *cpumap)
+{
+    unsigned long ida, idb;
+    libxl_bitmap node_cpumap;
+    bool is_not = false, is_nodes = false;
+    int rc = 0;
+
+    libxl_bitmap_init(&node_cpumap);
+
+    rc = libxl_node_bitmap_alloc(ctx, &node_cpumap, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_node_bitmap_alloc failed.\n");
+        goto out;
+    }
+
+    /* Are we adding or removing cpus/nodes? */
+    if (STR_SKIP_PREFIX(str, "^")) {
+        is_not = true;
+    }
+
+    /* Are we dealing with cpus or full nodes? */
+    if (STR_SKIP_PREFIX(str, "node:") || STR_SKIP_PREFIX(str, "nodes:")) {
+        is_nodes = true;
+    }
+
+    if (strcmp(str, "all") == 0) {
+        /* We do not accept "^all" or "^nodes:all" */
+        if (is_not) {
+            fprintf(stderr, "Can't combine \"^\" and \"all\".\n");
+            rc = ERROR_INVAL;
+        } else
+            libxl_bitmap_set_any(cpumap);
+        goto out;
+    }
+
+    rc = parse_range(str, &ida, &idb);
+    if (rc) {
+        fprintf(stderr, "Invalid pcpu range: %s.\n", str);
+        goto out;
+    }
+
+    /* Add or remove the specified cpus in the range */
+    while (ida <= idb) {
+        if (is_nodes) {
+            /* Add/Remove all the cpus of a NUMA node */
+            int i;
+
+            rc = libxl_node_to_cpumap(ctx, ida, &node_cpumap);
+            if (rc) {
+                fprintf(stderr, "libxl_node_to_cpumap failed.\n");
+                goto out;
+            }
+
+            /* Add/Remove all the cpus in the node cpumap */
+            libxl_for_each_set_bit(i, node_cpumap) {
+                is_not ? libxl_bitmap_reset(cpumap, i) :
+                         libxl_bitmap_set(cpumap, i);
+            }
+        } else {
+            /* Add/Remove this cpu */
+            is_not ? libxl_bitmap_reset(cpumap, ida) :
+                     libxl_bitmap_set(cpumap, ida);
+        }
+        ida++;
+    }
+
+ out:
+    libxl_bitmap_dispose(&node_cpumap);
+    return rc;
+}
+
+/*
+ * Takes a string representing a set of cpus (specified either as
+ * single cpus or as eintire NUMA nodes) and turns it into the
+ * corresponding libxl_bitmap (in cpumap).
+ */
+int parse_cpurange(const char *cpu, libxl_bitmap *cpumap)
+{
+    char *ptr, *saveptr = NULL, *buf = xstrdup(cpu);
+    int rc = 0;
+
+    for (ptr = strtok_r(buf, ",", &saveptr); ptr;
+         ptr = strtok_r(NULL, ",", &saveptr)) {
+        rc = update_cpumap_range(ptr, cpumap);
+        if (rc)
+            break;
+    }
+    free(buf);
+
+    return rc;
+}
+
+static void parse_top_level_vnc_options(XLU_Config *config,
+                                        libxl_vnc_info *vnc)
+{
+    long l;
+
+    xlu_cfg_get_defbool(config, "vnc", &vnc->enable, 0);
+    xlu_cfg_replace_string (config, "vnclisten", &vnc->listen, 0);
+    xlu_cfg_replace_string (config, "vncpasswd", &vnc->passwd, 0);
+    if (!xlu_cfg_get_long (config, "vncdisplay", &l, 0))
+        vnc->display = l;
+    xlu_cfg_get_defbool(config, "vncunused", &vnc->findunused, 0);
+}
+
+static void parse_top_level_sdl_options(XLU_Config *config,
+                                        libxl_sdl_info *sdl)
+{
+    xlu_cfg_get_defbool(config, "sdl", &sdl->enable, 0);
+    xlu_cfg_get_defbool(config, "opengl", &sdl->opengl, 0);
+    xlu_cfg_replace_string (config, "display", &sdl->display, 0);
+    xlu_cfg_replace_string (config, "xauthority", &sdl->xauthority, 0);
+}
+
+static char *parse_cmdline(XLU_Config *config)
+{
+    char *cmdline = NULL;
+    const char *root = NULL, *extra = NULL, *buf = NULL;
+
+    xlu_cfg_get_string (config, "cmdline", &buf, 0);
+    xlu_cfg_get_string (config, "root", &root, 0);
+    xlu_cfg_get_string (config, "extra", &extra, 0);
+
+    if (buf) {
+        cmdline = strdup(buf);
+        if (root || extra)
+            fprintf(stderr, "Warning: ignoring root= and extra= "
+                    "in favour of cmdline=\n");
+    } else {
+        if (root && extra) {
+            xasprintf(&cmdline, "root=%s %s", root, extra);
+        } else if (root) {
+            xasprintf(&cmdline, "root=%s", root);
+        } else if (extra) {
+            cmdline = strdup(extra);
+        }
+    }
+
+    if ((buf || root || extra) && !cmdline) {
+        fprintf(stderr, "Failed to allocate memory for cmdline\n");
+        exit(EXIT_FAILURE);
+    }
+
+    return cmdline;
+}
+
+static void parse_vcpu_affinity(libxl_domain_build_info *b_info,
+                                XLU_ConfigList *cpus, const char *buf,
+                                int num_cpus, bool is_hard)
+{
+    libxl_bitmap *vcpu_affinity_array;
+
+    /*
+     * If we are here, and buf is !NULL, we're dealing with a string. What
+     * we do in this case is parse it, and copy the result in _all_ (up to
+     * b_info->max_vcpus) the elements of the vcpu affinity array.
+     *
+     * If buf is NULL, we have a list, and what we do is putting in the
+     * i-eth element of the vcpu affinity array the result of the parsing
+     * of the i-eth entry of the list. If there are more vcpus than
+     * entries, it is fine to just not touch the last array elements.
+     */
+
+    /* Silently ignore values corresponding to non existing vcpus */
+    if (buf || num_cpus > b_info->max_vcpus)
+        num_cpus = b_info->max_vcpus;
+
+    if (is_hard) {
+        b_info->num_vcpu_hard_affinity = num_cpus;
+        b_info->vcpu_hard_affinity = xmalloc(num_cpus * sizeof(libxl_bitmap));
+        vcpu_affinity_array = b_info->vcpu_hard_affinity;
+    } else {
+        b_info->num_vcpu_soft_affinity = num_cpus;
+        b_info->vcpu_soft_affinity = xmalloc(num_cpus * sizeof(libxl_bitmap));
+        vcpu_affinity_array = b_info->vcpu_soft_affinity;
+    }
+
+    if (!buf) {
+        int j = 0;
+
+        while ((buf = xlu_cfg_get_listitem(cpus, j)) != NULL && j < num_cpus) {
+            libxl_bitmap_init(&vcpu_affinity_array[j]);
+            if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[j], 0)) {
+                fprintf(stderr, "Unable to allocate cpumap for vcpu %d\n", j);
+                exit(EXIT_FAILURE);
+            }
+
+            if (parse_cpurange(buf, &vcpu_affinity_array[j]))
+                exit(EXIT_FAILURE);
+
+            j++;
+        }
+
+        /* We have a list of cpumaps, disable automatic placement */
+        libxl_defbool_set(&b_info->numa_placement, false);
+    } else {
+        int i;
+
+        libxl_bitmap_init(&vcpu_affinity_array[0]);
+        if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[0], 0)) {
+            fprintf(stderr, "Unable to allocate cpumap for vcpu 0\n");
+            exit(EXIT_FAILURE);
+        }
+
+        if (parse_cpurange(buf, &vcpu_affinity_array[0]))
+            exit(EXIT_FAILURE);
+
+        for (i = 1; i < b_info->max_vcpus; i++) {
+            libxl_bitmap_init(&vcpu_affinity_array[i]);
+            if (libxl_cpu_bitmap_alloc(ctx, &vcpu_affinity_array[i], 0)) {
+                fprintf(stderr, "Unable to allocate cpumap for vcpu %d\n", i);
+                exit(EXIT_FAILURE);
+            }
+            libxl_bitmap_copy(ctx, &vcpu_affinity_array[i],
+                              &vcpu_affinity_array[0]);
+        }
+
+        libxl_defbool_set(&b_info->numa_placement, false);
+    }
+}
+
+static unsigned long parse_ulong(const char *str)
+{
+    char *endptr;
+    unsigned long val;
+
+    val = strtoul(str, &endptr, 10);
+    if (endptr == str || val == ULONG_MAX) {
+        fprintf(stderr, "xl: failed to convert \"%s\" to number\n", str);
+        exit(EXIT_FAILURE);
+    }
+    return val;
+}
+
+void replace_string(char **str, const char *val)
+{
+    free(*str);
+    *str = xstrdup(val);
+}
+
+int match_option_size(const char *prefix, size_t len,
+                      char *arg, char **argopt)
+{
+    int rc = strncmp(prefix, arg, len);
+    if (!rc) *argopt = arg+len;
+    return !rc;
+}
+
+/* Parses network data and adds info into nic
+ * Returns 1 if the input token does not match one of the keys
+ * or parsed values are not correct. Successful parse returns 0 */
+int parse_nic_config(libxl_device_nic *nic, XLU_Config **config, char *token)
+{
+    char *endptr, *oparg;
+    int i;
+    unsigned int val;
+
+    if (MATCH_OPTION("type", token, oparg)) {
+        if (!strcmp("vif", oparg)) {
+            nic->nictype = LIBXL_NIC_TYPE_VIF;
+        } else if (!strcmp("ioemu", oparg)) {
+            nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU;
+        } else {
+            fprintf(stderr, "Invalid parameter `type'.\n");
+            return 1;
+        }
+    } else if (MATCH_OPTION("mac", token, oparg)) {
+        for (i = 0; i < 6; i++) {
+            val = strtoul(oparg, &endptr, 16);
+            if ((oparg == endptr) || (val > 255)) {
+                fprintf(stderr, "Invalid parameter `mac'.\n");
+                return 1;
+            }
+            nic->mac[i] = val;
+            oparg = endptr + 1;
+        }
+    } else if (MATCH_OPTION("bridge", token, oparg)) {
+        replace_string(&nic->bridge, oparg);
+    } else if (MATCH_OPTION("netdev", token, oparg)) {
+        fprintf(stderr, "the netdev parameter is deprecated, "
+                        "please use gatewaydev instead\n");
+        replace_string(&nic->gatewaydev, oparg);
+    } else if (MATCH_OPTION("gatewaydev", token, oparg)) {
+        replace_string(&nic->gatewaydev, oparg);
+    } else if (MATCH_OPTION("ip", token, oparg)) {
+        replace_string(&nic->ip, oparg);
+    } else if (MATCH_OPTION("script", token, oparg)) {
+        replace_string(&nic->script, oparg);
+    } else if (MATCH_OPTION("backend", token, oparg)) {
+        replace_string(&nic->backend_domname, oparg);
+    } else if (MATCH_OPTION("vifname", token, oparg)) {
+        replace_string(&nic->ifname, oparg);
+    } else if (MATCH_OPTION("model", token, oparg)) {
+        replace_string(&nic->model, oparg);
+    } else if (MATCH_OPTION("rate", token, oparg)) {
+        parse_vif_rate(config, oparg, nic);
+    } else if (MATCH_OPTION("forwarddev", token, oparg)) {
+        replace_string(&nic->coloft_forwarddev, oparg);
+    } else if (MATCH_OPTION("accel", token, oparg)) {
+        fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
+    } else if (MATCH_OPTION("devid", token, oparg)) {
+        nic->devid = parse_ulong(oparg);
+    } else {
+        fprintf(stderr, "unrecognized argument `%s'\n", token);
+        return 1;
+    }
+    return 0;
+}
+
+static void parse_vnuma_config(const XLU_Config *config,
+                               libxl_domain_build_info *b_info)
+{
+    libxl_physinfo physinfo;
+    uint32_t nr_nodes;
+    XLU_ConfigList *vnuma;
+    int i, j, len, num_vnuma;
+    unsigned long max_vcpus = 0, max_memkb = 0;
+    /* Temporary storage for parsed vcpus information to avoid
+     * parsing config twice. This array has num_vnuma elements.
+     */
+    libxl_bitmap *vcpu_parsed;
+
+    libxl_physinfo_init(&physinfo);
+    if (libxl_get_physinfo(ctx, &physinfo) != 0) {
+        libxl_physinfo_dispose(&physinfo);
+        fprintf(stderr, "libxl_get_physinfo failed\n");
+        exit(EXIT_FAILURE);
+    }
+
+    nr_nodes = physinfo.nr_nodes;
+    libxl_physinfo_dispose(&physinfo);
+
+    if (xlu_cfg_get_list(config, "vnuma", &vnuma, &num_vnuma, 1))
+        return;
+
+    if (!num_vnuma)
+        return;
+
+    b_info->num_vnuma_nodes = num_vnuma;
+    b_info->vnuma_nodes = xcalloc(num_vnuma, sizeof(libxl_vnode_info));
+    vcpu_parsed = xcalloc(num_vnuma, sizeof(libxl_bitmap));
+    for (i = 0; i < num_vnuma; i++) {
+        libxl_bitmap_init(&vcpu_parsed[i]);
+        if (libxl_cpu_bitmap_alloc(ctx, &vcpu_parsed[i], b_info->max_vcpus)) {
+            fprintf(stderr, "libxl_node_bitmap_alloc failed.\n");
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    for (i = 0; i < b_info->num_vnuma_nodes; i++) {
+        libxl_vnode_info *p = &b_info->vnuma_nodes[i];
+
+        libxl_vnode_info_init(p);
+        p->distances = xcalloc(b_info->num_vnuma_nodes,
+                               sizeof(*p->distances));
+        p->num_distances = b_info->num_vnuma_nodes;
+    }
+
+    for (i = 0; i < num_vnuma; i++) {
+        XLU_ConfigValue *vnode_spec, *conf_option;
+        XLU_ConfigList *vnode_config_list;
+        int conf_count;
+        libxl_vnode_info *p = &b_info->vnuma_nodes[i];
+
+        vnode_spec = xlu_cfg_get_listitem2(vnuma, i);
+        assert(vnode_spec);
+
+        xlu_cfg_value_get_list(config, vnode_spec, &vnode_config_list, 0);
+        if (!vnode_config_list) {
+            fprintf(stderr, "xl: cannot get vnode config option list\n");
+            exit(EXIT_FAILURE);
+        }
+
+        for (conf_count = 0;
+             (conf_option =
+              xlu_cfg_get_listitem2(vnode_config_list, conf_count));
+             conf_count++) {
+
+            if (xlu_cfg_value_type(conf_option) == XLU_STRING) {
+                char *buf, *option_untrimmed, *value_untrimmed;
+                char *option, *value;
+                unsigned long val;
+
+                xlu_cfg_value_get_string(config, conf_option, &buf, 0);
+
+                if (!buf) continue;
+
+                if (split_string_into_pair(buf, "=",
+                                           &option_untrimmed,
+                                           &value_untrimmed)) {
+                    fprintf(stderr, "xl: failed to split \"%s\" into pair\n",
+                            buf);
+                    exit(EXIT_FAILURE);
+                }
+                trim(isspace, option_untrimmed, &option);
+                trim(isspace, value_untrimmed, &value);
+
+                if (!strcmp("pnode", option)) {
+                    val = parse_ulong(value);
+                    if (val >= nr_nodes) {
+                        fprintf(stderr,
+                                "xl: invalid pnode number: %lu\n", val);
+                        exit(EXIT_FAILURE);
+                    }
+                    p->pnode = val;
+                    libxl_defbool_set(&b_info->numa_placement, false);
+                } else if (!strcmp("size", option)) {
+                    val = parse_ulong(value);
+                    p->memkb = val << 10;
+                    max_memkb += p->memkb;
+                } else if (!strcmp("vcpus", option)) {
+                    libxl_string_list cpu_spec_list;
+                    unsigned long s, e;
+
+                    split_string_into_string_list(value, ",", &cpu_spec_list);
+                    len = libxl_string_list_length(&cpu_spec_list);
+
+                    for (j = 0; j < len; j++) {
+                        parse_range(cpu_spec_list[j], &s, &e);
+                        for (; s <= e; s++) {
+                            /*
+                             * Note that if we try to set a bit beyond
+                             * the size of bitmap, libxl_bitmap_set
+                             * has no effect. The resulted bitmap
+                             * doesn't reflect what user wants. The
+                             * fallout is dealt with later after
+                             * parsing.
+                             */
+                            libxl_bitmap_set(&vcpu_parsed[i], s);
+                            max_vcpus++;
+                        }
+                    }
+
+                    libxl_string_list_dispose(&cpu_spec_list);
+                } else if (!strcmp("vdistances", option)) {
+                    libxl_string_list vdist;
+
+                    split_string_into_string_list(value, ",", &vdist);
+                    len = libxl_string_list_length(&vdist);
+
+                    for (j = 0; j < len; j++) {
+                        val = parse_ulong(vdist[j]);
+                        p->distances[j] = val;
+                    }
+                    libxl_string_list_dispose(&vdist);
+                }
+                free(option);
+                free(value);
+                free(option_untrimmed);
+                free(value_untrimmed);
+            }
+        }
+    }
+
+    /* User has specified maxvcpus= */
+    if (b_info->max_vcpus != 0) {
+        if (b_info->max_vcpus != max_vcpus) {
+            fprintf(stderr, "xl: vnuma vcpus and maxvcpus= mismatch\n");
+            exit(EXIT_FAILURE);
+        }
+    } else {
+        int host_cpus = libxl_get_online_cpus(ctx);
+
+        if (host_cpus < 0) {
+            fprintf(stderr, "Failed to get online cpus\n");
+            exit(EXIT_FAILURE);
+        }
+
+        if (host_cpus < max_vcpus) {
+            fprintf(stderr, "xl: vnuma specifies more vcpus than pcpus, "\
+                    "use maxvcpus= to override this check.\n");
+            exit(EXIT_FAILURE);
+        }
+
+        b_info->max_vcpus = max_vcpus;
+    }
+
+    /* User has specified maxmem= */
+    if (b_info->max_memkb != LIBXL_MEMKB_DEFAULT &&
+        b_info->max_memkb != max_memkb) {
+        fprintf(stderr, "xl: maxmem and vnuma memory size mismatch\n");
+        exit(EXIT_FAILURE);
+    } else
+        b_info->max_memkb = max_memkb;
+
+    for (i = 0; i < b_info->num_vnuma_nodes; i++) {
+        libxl_vnode_info *p = &b_info->vnuma_nodes[i];
+
+        libxl_bitmap_copy_alloc(ctx, &p->vcpus, &vcpu_parsed[i]);
+        libxl_bitmap_dispose(&vcpu_parsed[i]);
+    }
+
+    free(vcpu_parsed);
+}
+
+/* Parses usbctrl data and adds info into usbctrl
+ * Returns 1 if the input token does not match one of the keys
+ * or parsed values are not correct. Successful parse returns 0 */
+int parse_usbctrl_config(libxl_device_usbctrl *usbctrl, char *token)
+{
+    char *oparg;
+
+    if (MATCH_OPTION("type", token, oparg)) {
+        if (libxl_usbctrl_type_from_string(oparg, &usbctrl->type)) {
+            fprintf(stderr, "Invalid usb controller type '%s'\n", oparg);
+            return 1;
+        }
+    } else if (MATCH_OPTION("version", token, oparg)) {
+        usbctrl->version = atoi(oparg);
+    } else if (MATCH_OPTION("ports", token, oparg)) {
+        usbctrl->ports = atoi(oparg);
+    } else {
+        fprintf(stderr, "Unknown string `%s' in usbctrl spec\n", token);
+        return 1;
+    }
+
+    return 0;
+}
+
+/* Parses usbdev data and adds info into usbdev
+ * Returns 1 if the input token does not match one of the keys
+ * or parsed values are not correct. Successful parse returns 0 */
+int parse_usbdev_config(libxl_device_usbdev *usbdev, char *token)
+{
+    char *oparg;
+
+    if (MATCH_OPTION("type", token, oparg)) {
+        if (libxl_usbdev_type_from_string(oparg, &usbdev->type)) {
+            fprintf(stderr, "Invalid usb device type: %s\n", optarg);
+            return 1;
+        }
+    } else if (MATCH_OPTION("hostbus", token, oparg)) {
+        usbdev->u.hostdev.hostbus = strtoul(oparg, NULL, 0);
+    } else if (MATCH_OPTION("hostaddr", token, oparg)) {
+        usbdev->u.hostdev.hostaddr = strtoul(oparg, NULL, 0);
+    } else if (MATCH_OPTION("controller", token, oparg)) {
+        usbdev->ctrl = atoi(oparg);
+    } else if (MATCH_OPTION("port", token, oparg)) {
+        usbdev->port = atoi(oparg);
+    } else {
+        fprintf(stderr, "Unknown string `%s' in usbdev spec\n", token);
+        return 1;
+    }
+
+    return 0;
+}
+
+void parse_config_data(const char *config_source,
+                       const char *config_data,
+                       int config_len,
+                       libxl_domain_config *d_config)
+{
+    const char *buf;
+    long l, vcpus = 0;
+    XLU_Config *config;
+    XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms,
+                   *usbctrls, *usbdevs;
+    XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs;
+    int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian;
+    int pci_power_mgmt = 0;
+    int pci_msitranslate = 0;
+    int pci_permissive = 0;
+    int pci_seize = 0;
+    int i, e;
+    char *kernel_basename;
+
+    libxl_domain_create_info *c_info = &d_config->c_info;
+    libxl_domain_build_info *b_info = &d_config->b_info;
+
+    config= xlu_cfg_init(stderr, config_source);
+    if (!config) {
+        fprintf(stderr, "Failed to allocate for configuration\n");
+        exit(1);
+    }
+
+    e= xlu_cfg_readdata(config, config_data, config_len);
+    if (e) {
+        fprintf(stderr, "Failed to parse config: %s\n", strerror(e));
+        exit(1);
+    }
+
+    if (!xlu_cfg_get_string (config, "init_seclabel", &buf, 0))
+        xlu_cfg_replace_string(config, "init_seclabel",
+                               &c_info->ssid_label, 0);
+
+    if (!xlu_cfg_get_string (config, "seclabel", &buf, 0)) {
+        if (c_info->ssid_label)
+            xlu_cfg_replace_string(config, "seclabel",
+                                   &b_info->exec_ssid_label, 0);
+        else
+            xlu_cfg_replace_string(config, "seclabel",
+                                   &c_info->ssid_label, 0);
+    }
+
+    libxl_defbool_set(&c_info->run_hotplug_scripts, run_hotplug_scripts);
+    c_info->type = LIBXL_DOMAIN_TYPE_PV;
+    if (!xlu_cfg_get_string (config, "builder", &buf, 0) &&
+        !strncmp(buf, "hvm", strlen(buf)))
+        c_info->type = LIBXL_DOMAIN_TYPE_HVM;
+
+    xlu_cfg_get_defbool(config, "pvh", &c_info->pvh, 0);
+    xlu_cfg_get_defbool(config, "hap", &c_info->hap, 0);
+
+    if (xlu_cfg_replace_string (config, "name", &c_info->name, 0)) {
+        fprintf(stderr, "Domain name must be specified.\n");
+        exit(1);
+    }
+
+    if (!xlu_cfg_get_string (config, "uuid", &buf, 0) ) {
+        if ( libxl_uuid_from_string(&c_info->uuid, buf) ) {
+            fprintf(stderr, "Failed to parse UUID: %s\n", buf);
+            exit(1);
+        }
+    }else{
+        libxl_uuid_generate(&c_info->uuid);
+    }
+
+    xlu_cfg_get_defbool(config, "oos", &c_info->oos, 0);
+
+    if (!xlu_cfg_get_string (config, "pool", &buf, 0))
+        xlu_cfg_replace_string(config, "pool", &c_info->pool_name, 0);
+
+    libxl_domain_build_info_init_type(b_info, c_info->type);
+    if (blkdev_start)
+        b_info->blkdev_start = strdup(blkdev_start);
+
+    /* the following is the actual config parsing with overriding
+     * values in the structures */
+    if (!xlu_cfg_get_long (config, "cpu_weight", &l, 0))
+        b_info->sched_params.weight = l;
+    if (!xlu_cfg_get_long (config, "cap", &l, 0))
+        b_info->sched_params.cap = l;
+    if (!xlu_cfg_get_long (config, "period", &l, 0))
+        b_info->sched_params.period = l;
+    if (!xlu_cfg_get_long (config, "slice", &l, 0))
+        b_info->sched_params.slice = l;
+    if (!xlu_cfg_get_long (config, "latency", &l, 0))
+        b_info->sched_params.latency = l;
+    if (!xlu_cfg_get_long (config, "extratime", &l, 0))
+        b_info->sched_params.extratime = l;
+
+    if (!xlu_cfg_get_long (config, "memory", &l, 0))
+        b_info->target_memkb = l * 1024;
+
+    if (!xlu_cfg_get_long (config, "maxmem", &l, 0))
+        b_info->max_memkb = l * 1024;
+
+    if (!xlu_cfg_get_long (config, "vcpus", &l, 0)) {
+        vcpus = l;
+        if (libxl_cpu_bitmap_alloc(ctx, &b_info->avail_vcpus, l)) {
+            fprintf(stderr, "Unable to allocate cpumap\n");
+            exit(1);
+        }
+        libxl_bitmap_set_none(&b_info->avail_vcpus);
+        while (l-- > 0)
+            libxl_bitmap_set((&b_info->avail_vcpus), l);
+    }
+
+    if (!xlu_cfg_get_long (config, "maxvcpus", &l, 0))
+        b_info->max_vcpus = l;
+
+    parse_vnuma_config(config, b_info);
+
+    /* Set max_memkb to target_memkb and max_vcpus to avail_vcpus if
+     * they are not set by user specified config option or vnuma.
+     */
+    if (b_info->max_memkb == LIBXL_MEMKB_DEFAULT)
+        b_info->max_memkb = b_info->target_memkb;
+    if (b_info->max_vcpus == 0)
+        b_info->max_vcpus = vcpus;
+
+    if (b_info->max_vcpus < vcpus) {
+        fprintf(stderr, "xl: maxvcpus < vcpus\n");
+        exit(1);
+    }
+
+    buf = NULL;
+    if (!xlu_cfg_get_list (config, "cpus", &cpus, &num_cpus, 1) ||
+        !xlu_cfg_get_string (config, "cpus", &buf, 0))
+        parse_vcpu_affinity(b_info, cpus, buf, num_cpus, /* is_hard */ true);
+
+    buf = NULL;
+    if (!xlu_cfg_get_list (config, "cpus_soft", &cpus, &num_cpus, 1) ||
+        !xlu_cfg_get_string (config, "cpus_soft", &buf, 0))
+        parse_vcpu_affinity(b_info, cpus, buf, num_cpus, false);
+
+    libxl_defbool_set(&b_info->claim_mode, claim_mode);
+
+    if (xlu_cfg_get_string (config, "on_poweroff", &buf, 0))
+        buf = "destroy";
+    if (!parse_action_on_shutdown(buf, &d_config->on_poweroff)) {
+        fprintf(stderr, "Unknown on_poweroff action \"%s\" specified\n", buf);
+        exit(1);
+    }
+
+    if (xlu_cfg_get_string (config, "on_reboot", &buf, 0))
+        buf = "restart";
+    if (!parse_action_on_shutdown(buf, &d_config->on_reboot)) {
+        fprintf(stderr, "Unknown on_reboot action \"%s\" specified\n", buf);
+        exit(1);
+    }
+
+    if (xlu_cfg_get_string (config, "on_watchdog", &buf, 0))
+        buf = "destroy";
+    if (!parse_action_on_shutdown(buf, &d_config->on_watchdog)) {
+        fprintf(stderr, "Unknown on_watchdog action \"%s\" specified\n", buf);
+        exit(1);
+    }
+
+
+    if (xlu_cfg_get_string (config, "on_crash", &buf, 0))
+        buf = "destroy";
+    if (!parse_action_on_shutdown(buf, &d_config->on_crash)) {
+        fprintf(stderr, "Unknown on_crash action \"%s\" specified\n", buf);
+        exit(1);
+    }
+
+    if (xlu_cfg_get_string (config, "on_soft_reset", &buf, 0))
+        buf = "soft-reset";
+    if (!parse_action_on_shutdown(buf, &d_config->on_soft_reset)) {
+        fprintf(stderr, "Unknown on_soft_reset action \"%s\" specified\n", buf);
+        exit(1);
+    }
+
+    /* libxl_get_required_shadow_memory() must be called after final values
+     * (default or specified) for vcpus and memory are set, because the
+     * calculation depends on those values. */
+    b_info->shadow_memkb = !xlu_cfg_get_long(config, "shadow_memory", &l, 0)
+        ? l * 1024
+        : libxl_get_required_shadow_memory(b_info->max_memkb,
+                                           b_info->max_vcpus);
+
+    xlu_cfg_get_defbool(config, "nomigrate", &b_info->disable_migrate, 0);
+
+    if (!xlu_cfg_get_long(config, "tsc_mode", &l, 1)) {
+        const char *s = libxl_tsc_mode_to_string(l);
+        fprintf(stderr, "WARNING: specifying \"tsc_mode\" as an integer is deprecated. "
+                "Please use the named parameter variant. %s%s%s\n",
+                s ? "e.g. tsc_mode=\"" : "",
+                s ? s : "",
+                s ? "\"" : "");
+
+        if (l < LIBXL_TSC_MODE_DEFAULT ||
+            l > LIBXL_TSC_MODE_NATIVE_PARAVIRT) {
+            fprintf(stderr, "ERROR: invalid value %ld for \"tsc_mode\"\n", l);
+            exit (1);
+        }
+        b_info->tsc_mode = l;
+    } else if (!xlu_cfg_get_string(config, "tsc_mode", &buf, 0)) {
+        fprintf(stderr, "got a tsc mode string: \"%s\"\n", buf);
+        if (libxl_tsc_mode_from_string(buf, &b_info->tsc_mode)) {
+            fprintf(stderr, "ERROR: invalid value \"%s\" for \"tsc_mode\"\n",
+                    buf);
+            exit (1);
+        }
+    }
+
+    if (!xlu_cfg_get_long(config, "rtc_timeoffset", &l, 0))
+        b_info->rtc_timeoffset = l;
+
+    if (!xlu_cfg_get_long(config, "vncviewer", &l, 0))
+        fprintf(stderr, "WARNING: ignoring \"vncviewer\" option. "
+                "Use \"-V\" option of \"xl create\" to automatically spawn vncviewer.\n");
+
+    xlu_cfg_get_defbool(config, "localtime", &b_info->localtime, 0);
+
+    if (!xlu_cfg_get_long (config, "videoram", &l, 0))
+        b_info->video_memkb = l * 1024;
+
+    if (!xlu_cfg_get_long(config, "max_event_channels", &l, 0))
+        b_info->event_channels = l;
+
+    xlu_cfg_replace_string (config, "kernel", &b_info->kernel, 0);
+    xlu_cfg_replace_string (config, "ramdisk", &b_info->ramdisk, 0);
+    xlu_cfg_replace_string (config, "device_tree", &b_info->device_tree, 0);
+    b_info->cmdline = parse_cmdline(config);
+
+    xlu_cfg_get_defbool(config, "driver_domain", &c_info->driver_domain, 0);
+    xlu_cfg_get_defbool(config, "acpi", &b_info->acpi, 0);
+
+    switch(b_info->type) {
+    case LIBXL_DOMAIN_TYPE_HVM:
+        kernel_basename = libxl_basename(b_info->kernel);
+        if (!strcmp(kernel_basename, "hvmloader")) {
+            fprintf(stderr, "WARNING: you seem to be using \"kernel\" "
+                    "directive to override HVM guest firmware. Ignore "
+                    "that. Use \"firmware_override\" instead if you "
+                    "really want a non-default firmware\n");
+            b_info->kernel = NULL;
+        }
+        free(kernel_basename);
+
+        xlu_cfg_replace_string (config, "firmware_override",
+                                &b_info->u.hvm.firmware, 0);
+        xlu_cfg_replace_string (config, "bios_path_override",
+                                &b_info->u.hvm.system_firmware, 0);
+        if (!xlu_cfg_get_string(config, "bios", &buf, 0)) {
+            if (libxl_bios_type_from_string(buf, &b_info->u.hvm.bios)) {
+                fprintf(stderr, "ERROR: invalid value \"%s\" for \"bios\"\n",
+                    buf);
+                exit (1);
+            }
+        } else if (b_info->u.hvm.system_firmware)
+            fprintf(stderr, "WARNING: "
+                    "bios_path_override given without specific bios name\n");
+
+        xlu_cfg_get_defbool(config, "pae", &b_info->u.hvm.pae, 0);
+        xlu_cfg_get_defbool(config, "apic", &b_info->u.hvm.apic, 0);
+        xlu_cfg_get_defbool(config, "acpi_s3", &b_info->u.hvm.acpi_s3, 0);
+        xlu_cfg_get_defbool(config, "acpi_s4", &b_info->u.hvm.acpi_s4, 0);
+        xlu_cfg_get_defbool(config, "nx", &b_info->u.hvm.nx, 0);
+        xlu_cfg_get_defbool(config, "hpet", &b_info->u.hvm.hpet, 0);
+        xlu_cfg_get_defbool(config, "vpt_align", &b_info->u.hvm.vpt_align, 0);
+
+        switch (xlu_cfg_get_list(config, "viridian",
+                                 &viridian, &num_viridian, 1))
+        {
+        case 0: /* Success */
+            if (num_viridian) {
+                libxl_bitmap_alloc(ctx, &b_info->u.hvm.viridian_enable,
+                                   LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
+                libxl_bitmap_alloc(ctx, &b_info->u.hvm.viridian_disable,
+                                   LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
+            }
+            for (i = 0; i < num_viridian; i++) {
+                libxl_viridian_enlightenment v;
+
+                buf = xlu_cfg_get_listitem(viridian, i);
+                if (strcmp(buf, "all") == 0)
+                    libxl_bitmap_set_any(&b_info->u.hvm.viridian_enable);
+                else if (strcmp(buf, "defaults") == 0)
+                    libxl_defbool_set(&b_info->u.hvm.viridian, true);
+                else {
+                    libxl_bitmap *s = &b_info->u.hvm.viridian_enable;
+                    libxl_bitmap *r = &b_info->u.hvm.viridian_disable;
+
+                    if (*buf == '!') {
+                        s = &b_info->u.hvm.viridian_disable;
+                        r = &b_info->u.hvm.viridian_enable;
+                        buf++;
+                    }
+
+                    e = libxl_viridian_enlightenment_from_string(buf, &v);
+                    if (e) {
+                        fprintf(stderr,
+                                "xl: unknown viridian enlightenment '%s'\n",
+                                buf);
+                        exit(-ERROR_FAIL);
+                    }
+
+                    libxl_bitmap_set(s, v);
+                    libxl_bitmap_reset(r, v);
+                }
+            }
+            break;
+        case ESRCH: break; /* Option not present */
+        case EINVAL:
+            xlu_cfg_get_defbool(config, "viridian", &b_info->u.hvm.viridian, 1);
+            break;
+        default:
+            fprintf(stderr,"xl: Unable to parse viridian enlightenments.\n");
+            exit(-ERROR_FAIL);
+        }
+
+        if (!xlu_cfg_get_long(config, "mmio_hole", &l, 0)) {
+            uint64_t mmio_hole_size;
+
+            b_info->u.hvm.mmio_hole_memkb = l * 1024;
+            mmio_hole_size = b_info->u.hvm.mmio_hole_memkb * 1024;
+            if (mmio_hole_size < HVM_BELOW_4G_MMIO_LENGTH ||
+                mmio_hole_size > HVM_BELOW_4G_MMIO_START) {
+                fprintf(stderr,
+                        "ERROR: invalid value %ld for \"mmio_hole\"\n", l);
+                exit (1);
+            }
+        }
+        if (!xlu_cfg_get_long(config, "timer_mode", &l, 1)) {
+            const char *s = libxl_timer_mode_to_string(l);
+            fprintf(stderr, "WARNING: specifying \"timer_mode\" as an integer is deprecated. "
+                    "Please use the named parameter variant. %s%s%s\n",
+                    s ? "e.g. timer_mode=\"" : "",
+                    s ? s : "",
+                    s ? "\"" : "");
+
+            if (l < LIBXL_TIMER_MODE_DELAY_FOR_MISSED_TICKS ||
+                l > LIBXL_TIMER_MODE_ONE_MISSED_TICK_PENDING) {
+                fprintf(stderr, "ERROR: invalid value %ld for \"timer_mode\"\n", l);
+                exit (1);
+            }
+            b_info->u.hvm.timer_mode = l;
+        } else if (!xlu_cfg_get_string(config, "timer_mode", &buf, 0)) {
+            if (libxl_timer_mode_from_string(buf, &b_info->u.hvm.timer_mode)) {
+                fprintf(stderr, "ERROR: invalid value \"%s\" for \"timer_mode\"\n",
+                        buf);
+                exit (1);
+            }
+        }
+
+        xlu_cfg_get_defbool(config, "nestedhvm", &b_info->u.hvm.nested_hvm, 0);
+
+        xlu_cfg_get_defbool(config, "altp2mhvm", &b_info->u.hvm.altp2m, 0);
+
+        xlu_cfg_replace_string(config, "smbios_firmware",
+                               &b_info->u.hvm.smbios_firmware, 0);
+        xlu_cfg_replace_string(config, "acpi_firmware",
+                               &b_info->u.hvm.acpi_firmware, 0);
+
+        if (!xlu_cfg_get_string(config, "ms_vm_genid", &buf, 0)) {
+            if (!strcmp(buf, "generate")) {
+                e = libxl_ms_vm_genid_generate(ctx, &b_info->u.hvm.ms_vm_genid);
+                if (e) {
+                    fprintf(stderr, "ERROR: failed to generate a VM Generation ID\n");
+                    exit(1);
+                }
+            } else if (!strcmp(buf, "none")) {
+                ;
+            } else {
+                    fprintf(stderr, "ERROR: \"ms_vm_genid\" option must be \"generate\" or \"none\"\n");
+                    exit(1);
+            }
+        }
+
+        if (!xlu_cfg_get_long (config, "rdm_mem_boundary", &l, 0))
+            b_info->u.hvm.rdm_mem_boundary_memkb = l * 1024;
+        break;
+    case LIBXL_DOMAIN_TYPE_PV:
+    {
+        xlu_cfg_replace_string (config, "bootloader", &b_info->u.pv.bootloader, 0);
+        switch (xlu_cfg_get_list_as_string_list(config, "bootloader_args",
+                                      &b_info->u.pv.bootloader_args, 1))
+        {
+
+        case 0: break; /* Success */
+        case ESRCH: break; /* Option not present */
+        case EINVAL:
+            if (!xlu_cfg_get_string(config, "bootloader_args", &buf, 0)) {
+
+                fprintf(stderr, "WARNING: Specifying \"bootloader_args\""
+                        " as a string is deprecated. "
+                        "Please use a list of arguments.\n");
+                split_string_into_string_list(buf, " \t\n",
+                                              &b_info->u.pv.bootloader_args);
+            }
+            break;
+        default:
+            fprintf(stderr,"xl: Unable to parse bootloader_args.\n");
+            exit(-ERROR_FAIL);
+        }
+
+        if (!b_info->u.pv.bootloader && !b_info->kernel) {
+            fprintf(stderr, "Neither kernel nor bootloader specified\n");
+            exit(1);
+        }
+
+        break;
+    }
+    default:
+        abort();
+    }
+
+    if (!xlu_cfg_get_list(config, "ioports", &ioports, &num_ioports, 0)) {
+        b_info->num_ioports = num_ioports;
+        b_info->ioports = calloc(num_ioports, sizeof(*b_info->ioports));
+        if (b_info->ioports == NULL) {
+            fprintf(stderr, "unable to allocate memory for ioports\n");
+            exit(-1);
+        }
+
+        for (i = 0; i < num_ioports; i++) {
+            const char *buf2;
+            char *ep;
+            uint32_t start, end;
+            unsigned long ul;
+
+            buf = xlu_cfg_get_listitem (ioports, i);
+            if (!buf) {
+                fprintf(stderr,
+                        "xl: Unable to get element #%d in ioport list\n", i);
+                exit(1);
+            }
+            ul = strtoul(buf, &ep, 16);
+            if (ep == buf) {
+                fprintf(stderr, "xl: Invalid argument parsing ioport: %s\n",
+                        buf);
+                exit(1);
+            }
+            if (ul >= UINT32_MAX) {
+                fprintf(stderr, "xl: ioport %lx too big\n", ul);
+                exit(1);
+            }
+            start = end = ul;
+
+            if (*ep == '-') {
+                buf2 = ep + 1;
+                ul = strtoul(buf2, &ep, 16);
+                if (ep == buf2 || *ep != '\0' || start > end) {
+                    fprintf(stderr,
+                            "xl: Invalid argument parsing ioport: %s\n", buf);
+                    exit(1);
+                }
+                if (ul >= UINT32_MAX) {
+                    fprintf(stderr, "xl: ioport %lx too big\n", ul);
+                    exit(1);
+                }
+                end = ul;
+            } else if ( *ep != '\0' )
+                fprintf(stderr,
+                        "xl: Invalid argument parsing ioport: %s\n", buf);
+            b_info->ioports[i].first = start;
+            b_info->ioports[i].number = end - start + 1;
+        }
+    }
+
+    if (!xlu_cfg_get_list(config, "irqs", &irqs, &num_irqs, 0)) {
+        b_info->num_irqs = num_irqs;
+        b_info->irqs = calloc(num_irqs, sizeof(*b_info->irqs));
+        if (b_info->irqs == NULL) {
+            fprintf(stderr, "unable to allocate memory for ioports\n");
+            exit(-1);
+        }
+        for (i = 0; i < num_irqs; i++) {
+            char *ep;
+            unsigned long ul;
+            buf = xlu_cfg_get_listitem (irqs, i);
+            if (!buf) {
+                fprintf(stderr,
+                        "xl: Unable to get element %d in irq list\n", i);
+                exit(1);
+            }
+            ul = strtoul(buf, &ep, 10);
+            if (ep == buf || *ep != '\0') {
+                fprintf(stderr,
+                        "xl: Invalid argument parsing irq: %s\n", buf);
+                exit(1);
+            }
+            if (ul >= UINT32_MAX) {
+                fprintf(stderr, "xl: irq %lx too big\n", ul);
+                exit(1);
+            }
+            b_info->irqs[i] = ul;
+        }
+    }
+
+    if (!xlu_cfg_get_list(config, "iomem", &iomem, &num_iomem, 0)) {
+        int ret;
+        b_info->num_iomem = num_iomem;
+        b_info->iomem = calloc(num_iomem, sizeof(*b_info->iomem));
+        if (b_info->iomem == NULL) {
+            fprintf(stderr, "unable to allocate memory for iomem\n");
+            exit(-1);
+        }
+        for (i = 0; i < num_iomem; i++) {
+            int used;
+
+            buf = xlu_cfg_get_listitem (iomem, i);
+            if (!buf) {
+                fprintf(stderr,
+                        "xl: Unable to get element %d in iomem list\n", i);
+                exit(1);
+            }
+            libxl_iomem_range_init(&b_info->iomem[i]);
+            ret = sscanf(buf, "%" SCNx64",%" SCNx64"%n@%" SCNx64"%n",
+                         &b_info->iomem[i].start,
+                         &b_info->iomem[i].number, &used,
+                         &b_info->iomem[i].gfn, &used);
+            if (ret < 2 || buf[used] != '\0') {
+                fprintf(stderr,
+                        "xl: Invalid argument parsing iomem: %s\n", buf);
+                exit(1);
+            }
+        }
+    }
+
+
+
+    if (!xlu_cfg_get_list (config, "disk", &vbds, 0, 0)) {
+        d_config->num_disks = 0;
+        d_config->disks = NULL;
+        while ((buf = xlu_cfg_get_listitem (vbds, d_config->num_disks)) != NULL) {
+            libxl_device_disk *disk;
+            char *buf2 = strdup(buf);
+
+            disk = ARRAY_EXTEND_INIT_NODEVID(d_config->disks,
+                                             d_config->num_disks,
+                                             libxl_device_disk_init);
+            parse_disk_config(&config, buf2, disk);
+
+            free(buf2);
+        }
+    }
+
+    if (!xlu_cfg_get_list(config, "vtpm", &vtpms, 0, 0)) {
+        d_config->num_vtpms = 0;
+        d_config->vtpms = NULL;
+        while ((buf = xlu_cfg_get_listitem (vtpms, d_config->num_vtpms)) != NULL) {
+            libxl_device_vtpm *vtpm;
+            char * buf2 = strdup(buf);
+            char *p, *p2;
+            bool got_backend = false;
+
+            vtpm = ARRAY_EXTEND_INIT(d_config->vtpms,
+                                     d_config->num_vtpms,
+                                     libxl_device_vtpm_init);
+
+            p = strtok(buf2, ",");
+            if(p) {
+               do {
+                  while(*p == ' ')
+                     ++p;
+                  if ((p2 = strchr(p, '=')) == NULL)
+                     break;
+                  *p2 = '\0';
+                  if (!strcmp(p, "backend")) {
+                     vtpm->backend_domname = strdup(p2 + 1);
+                     got_backend = true;
+                  } else if(!strcmp(p, "uuid")) {
+                     if( libxl_uuid_from_string(&vtpm->uuid, p2 + 1) ) {
+                        fprintf(stderr,
+                              "Failed to parse vtpm UUID: %s\n", p2 + 1);
+                        exit(1);
+                    }
+                  } else {
+                     fprintf(stderr, "Unknown string `%s' in vtpm spec\n", p);
+                     exit(1);
+                  }
+               } while ((p = strtok(NULL, ",")) != NULL);
+            }
+            if(!got_backend) {
+               fprintf(stderr, "vtpm spec missing required backend field!\n");
+               exit(1);
+            }
+            free(buf2);
+        }
+    }
+
+    if (!xlu_cfg_get_list (config, "channel", &channels, 0, 0)) {
+        d_config->num_channels = 0;
+        d_config->channels = NULL;
+        while ((buf = xlu_cfg_get_listitem (channels,
+                d_config->num_channels)) != NULL) {
+            libxl_device_channel *chn;
+            libxl_string_list pairs;
+            char *path = NULL;
+            int len;
+
+            chn = ARRAY_EXTEND_INIT(d_config->channels, d_config->num_channels,
+                                   libxl_device_channel_init);
+
+            split_string_into_string_list(buf, ",", &pairs);
+            len = libxl_string_list_length(&pairs);
+            for (i = 0; i < len; i++) {
+                char *key, *key_untrimmed, *value, *value_untrimmed;
+                int rc;
+                rc = split_string_into_pair(pairs[i], "=",
+                                            &key_untrimmed,
+                                            &value_untrimmed);
+                if (rc != 0) {
+                    fprintf(stderr, "failed to parse channel configuration: %s",
+                            pairs[i]);
+                    exit(1);
+                }
+                trim(isspace, key_untrimmed, &key);
+                trim(isspace, value_untrimmed, &value);
+
+                if (!strcmp(key, "backend")) {
+                    replace_string(&chn->backend_domname, value);
+                } else if (!strcmp(key, "name")) {
+                    replace_string(&chn->name, value);
+                } else if (!strcmp(key, "path")) {
+                    replace_string(&path, value);
+                } else if (!strcmp(key, "connection")) {
+                    if (!strcmp(value, "pty")) {
+                        chn->connection = LIBXL_CHANNEL_CONNECTION_PTY;
+                    } else if (!strcmp(value, "socket")) {
+                        chn->connection = LIBXL_CHANNEL_CONNECTION_SOCKET;
+                    } else {
+                        fprintf(stderr, "unknown channel connection '%s'\n",
+                                value);
+                        exit(1);
+                    }
+                } else {
+                    fprintf(stderr, "unknown channel parameter '%s',"
+                                  " ignoring\n", key);
+                }
+                free(key);
+                free(key_untrimmed);
+                free(value);
+                free(value_untrimmed);
+            }
+            switch (chn->connection) {
+            case LIBXL_CHANNEL_CONNECTION_UNKNOWN:
+                fprintf(stderr, "channel has unknown 'connection'\n");
+                exit(1);
+            case LIBXL_CHANNEL_CONNECTION_SOCKET:
+                if (!path) {
+                    fprintf(stderr, "channel connection 'socket' requires path=..\n");
+                    exit(1);
+                }
+                chn->u.socket.path = xstrdup(path);
+                break;
+            case LIBXL_CHANNEL_CONNECTION_PTY:
+                /* Nothing to do since PTY has no arguments */
+                break;
+            default:
+                fprintf(stderr, "unknown channel connection: %d",
+                        chn->connection);
+                exit(1);
+            }
+            libxl_string_list_dispose(&pairs);
+            free(path);
+        }
+    }
+
+    if (!xlu_cfg_get_list (config, "vif", &nics, 0, 0)) {
+        d_config->num_nics = 0;
+        d_config->nics = NULL;
+        while ((buf = xlu_cfg_get_listitem (nics, d_config->num_nics)) != NULL) {
+            libxl_device_nic *nic;
+            char *buf2 = strdup(buf);
+            char *p;
+
+            nic = ARRAY_EXTEND_INIT(d_config->nics,
+                                    d_config->num_nics,
+                                    libxl_device_nic_init);
+            set_default_nic_values(nic);
+
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip_nic;
+            do {
+                while (*p == ' ')
+                    p++;
+                parse_nic_config(nic, &config, p);
+            } while ((p = strtok(NULL, ",")) != NULL);
+skip_nic:
+            free(buf2);
+        }
+    }
+
+    if (!xlu_cfg_get_list(config, "vif2", NULL, 0, 0)) {
+        fprintf(stderr, "WARNING: vif2: netchannel2 is deprecated and not supported by xl\n");
+    }
+
+    d_config->num_vfbs = 0;
+    d_config->num_vkbs = 0;
+    d_config->vfbs = NULL;
+    d_config->vkbs = NULL;
+
+    if (!xlu_cfg_get_list (config, "vfb", &cvfbs, 0, 0)) {
+        while ((buf = xlu_cfg_get_listitem (cvfbs, d_config->num_vfbs)) != NULL) {
+            libxl_device_vfb *vfb;
+            libxl_device_vkb *vkb;
+
+            char *buf2 = strdup(buf);
+            char *p, *p2;
+
+            vfb = ARRAY_EXTEND_INIT(d_config->vfbs, d_config->num_vfbs,
+                                    libxl_device_vfb_init);
+
+            vkb = ARRAY_EXTEND_INIT(d_config->vkbs, d_config->num_vkbs,
+                                    libxl_device_vkb_init);
+
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip_vfb;
+            do {
+                while (*p == ' ')
+                    p++;
+                if ((p2 = strchr(p, '=')) == NULL)
+                    break;
+                *p2 = '\0';
+                if (!strcmp(p, "vnc")) {
+                    libxl_defbool_set(&vfb->vnc.enable, atoi(p2 + 1));
+                } else if (!strcmp(p, "vnclisten")) {
+                    free(vfb->vnc.listen);
+                    vfb->vnc.listen = strdup(p2 + 1);
+                } else if (!strcmp(p, "vncpasswd")) {
+                    free(vfb->vnc.passwd);
+                    vfb->vnc.passwd = strdup(p2 + 1);
+                } else if (!strcmp(p, "vncdisplay")) {
+                    vfb->vnc.display = atoi(p2 + 1);
+                } else if (!strcmp(p, "vncunused")) {
+                    libxl_defbool_set(&vfb->vnc.findunused, atoi(p2 + 1));
+                } else if (!strcmp(p, "keymap")) {
+                    free(vfb->keymap);
+                    vfb->keymap = strdup(p2 + 1);
+                } else if (!strcmp(p, "sdl")) {
+                    libxl_defbool_set(&vfb->sdl.enable, atoi(p2 + 1));
+                } else if (!strcmp(p, "opengl")) {
+                    libxl_defbool_set(&vfb->sdl.opengl, atoi(p2 + 1));
+                } else if (!strcmp(p, "display")) {
+                    free(vfb->sdl.display);
+                    vfb->sdl.display = strdup(p2 + 1);
+                } else if (!strcmp(p, "xauthority")) {
+                    free(vfb->sdl.xauthority);
+                    vfb->sdl.xauthority = strdup(p2 + 1);
+                }
+            } while ((p = strtok(NULL, ",")) != NULL);
+
+skip_vfb:
+            free(buf2);
+        }
+    }
+
+    if (!xlu_cfg_get_long (config, "pci_msitranslate", &l, 0))
+        pci_msitranslate = l;
+
+    if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l, 0))
+        pci_power_mgmt = l;
+
+    if (!xlu_cfg_get_long (config, "pci_permissive", &l, 0))
+        pci_permissive = l;
+
+    if (!xlu_cfg_get_long (config, "pci_seize", &l, 0))
+        pci_seize = l;
+
+    /* To be reworked (automatically enabled) once the auto ballooning
+     * after guest starts is done (with PCI devices passed in). */
+    if (c_info->type == LIBXL_DOMAIN_TYPE_PV) {
+        xlu_cfg_get_defbool(config, "e820_host", &b_info->u.pv.e820_host, 0);
+    }
+
+    if (!xlu_cfg_get_string(config, "rdm", &buf, 0)) {
+        libxl_rdm_reserve rdm;
+        if (!xlu_rdm_parse(config, &rdm, buf)) {
+            b_info->u.hvm.rdm.strategy = rdm.strategy;
+            b_info->u.hvm.rdm.policy = rdm.policy;
+        }
+    }
+
+    if (!xlu_cfg_get_list (config, "pci", &pcis, 0, 0)) {
+        d_config->num_pcidevs = 0;
+        d_config->pcidevs = NULL;
+        for(i = 0; (buf = xlu_cfg_get_listitem (pcis, i)) != NULL; i++) {
+            libxl_device_pci *pcidev;
+
+            pcidev = ARRAY_EXTEND_INIT_NODEVID(d_config->pcidevs,
+                                               d_config->num_pcidevs,
+                                               libxl_device_pci_init);
+            pcidev->msitranslate = pci_msitranslate;
+            pcidev->power_mgmt = pci_power_mgmt;
+            pcidev->permissive = pci_permissive;
+            pcidev->seize = pci_seize;
+            /*
+             * Like other pci option, the per-device policy always follows
+             * the global policy by default.
+             */
+            pcidev->rdm_policy = b_info->u.hvm.rdm.policy;
+            e = xlu_pci_parse_bdf(config, pcidev, buf);
+            if (e) {
+                fprintf(stderr,
+                        "unable to parse PCI BDF `%s' for passthrough\n",
+                        buf);
+                exit(-e);
+            }
+        }
+        if (d_config->num_pcidevs && c_info->type == LIBXL_DOMAIN_TYPE_PV)
+            libxl_defbool_set(&b_info->u.pv.e820_host, true);
+    }
+
+    if (!xlu_cfg_get_list (config, "dtdev", &dtdevs, 0, 0)) {
+        d_config->num_dtdevs = 0;
+        d_config->dtdevs = NULL;
+        for (i = 0; (buf = xlu_cfg_get_listitem(dtdevs, i)) != NULL; i++) {
+            libxl_device_dtdev *dtdev;
+
+            dtdev = ARRAY_EXTEND_INIT_NODEVID(d_config->dtdevs,
+                                              d_config->num_dtdevs,
+                                              libxl_device_dtdev_init);
+
+            dtdev->path = strdup(buf);
+            if (dtdev->path == NULL) {
+                fprintf(stderr, "unable to duplicate string for dtdevs\n");
+                exit(-1);
+            }
+        }
+    }
+
+    if (!xlu_cfg_get_list(config, "usbctrl", &usbctrls, 0, 0)) {
+        d_config->num_usbctrls = 0;
+        d_config->usbctrls = NULL;
+        while ((buf = xlu_cfg_get_listitem(usbctrls, d_config->num_usbctrls))
+               != NULL) {
+            libxl_device_usbctrl *usbctrl;
+            char *buf2 = strdup(buf);
+            char *p;
+
+            usbctrl = ARRAY_EXTEND_INIT(d_config->usbctrls,
+                                        d_config->num_usbctrls,
+                                        libxl_device_usbctrl_init);
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip_usbctrl;
+            do {
+                while (*p == ' ')
+                    p++;
+                if (parse_usbctrl_config(usbctrl, p))
+                    exit(1);
+            } while ((p = strtok(NULL, ",")) != NULL);
+skip_usbctrl:
+            free(buf2);
+        }
+    }
+
+    if (!xlu_cfg_get_list(config, "usbdev", &usbdevs, 0, 0)) {
+        d_config->num_usbdevs = 0;
+        d_config->usbdevs = NULL;
+        while ((buf = xlu_cfg_get_listitem(usbdevs, d_config->num_usbdevs))
+               != NULL) {
+            libxl_device_usbdev *usbdev;
+            char *buf2 = strdup(buf);
+            char *p;
+
+            usbdev = ARRAY_EXTEND_INIT_NODEVID(d_config->usbdevs,
+                                               d_config->num_usbdevs,
+                                               libxl_device_usbdev_init);
+            p = strtok(buf2, ",");
+            if (!p)
+                goto skip_usbdev;
+            do {
+                while (*p == ' ')
+                    p++;
+                if (parse_usbdev_config(usbdev, p))
+                    exit(1);
+            } while ((p = strtok(NULL, ",")) != NULL);
+skip_usbdev:
+            free(buf2);
+        }
+    }
+
+    switch (xlu_cfg_get_list(config, "cpuid", &cpuids, 0, 1)) {
+    case 0:
+        {
+            const char *errstr;
+
+            for (i = 0; (buf = xlu_cfg_get_listitem(cpuids, i)) != NULL; i++) {
+                e = libxl_cpuid_parse_config_xend(&b_info->cpuid, buf);
+                switch (e) {
+                case 0: continue;
+                case 1:
+                    errstr = "illegal leaf number";
+                    break;
+                case 2:
+                    errstr = "illegal subleaf number";
+                    break;
+                case 3:
+                    errstr = "missing colon";
+                    break;
+                case 4:
+                    errstr = "invalid register name (must be e[abcd]x)";
+                    break;
+                case 5:
+                    errstr = "policy string must be exactly 32 characters long";
+                    break;
+                default:
+                    errstr = "unknown error";
+                    break;
+                }
+                fprintf(stderr, "while parsing CPUID line: \"%s\":\n", buf);
+                fprintf(stderr, "  error #%i: %s\n", e, errstr);
+            }
+        }
+        break;
+    case EINVAL:    /* config option is not a list, parse as a string */
+        if (!xlu_cfg_get_string(config, "cpuid", &buf, 0)) {
+            char *buf2, *p, *strtok_ptr = NULL;
+            const char *errstr;
+
+            buf2 = strdup(buf);
+            p = strtok_r(buf2, ",", &strtok_ptr);
+            if (p == NULL) {
+                free(buf2);
+                break;
+            }
+            if (strcmp(p, "host")) {
+                fprintf(stderr, "while parsing CPUID string: \"%s\":\n", buf);
+                fprintf(stderr, "  error: first word must be \"host\"\n");
+                free(buf2);
+                break;
+            }
+            for (p = strtok_r(NULL, ",", &strtok_ptr); p != NULL;
+                 p = strtok_r(NULL, ",", &strtok_ptr)) {
+                e = libxl_cpuid_parse_config(&b_info->cpuid, p);
+                switch (e) {
+                case 0: continue;
+                case 1:
+                    errstr = "missing \"=\" in key=value";
+                    break;
+                case 2:
+                    errstr = "unknown CPUID flag name";
+                    break;
+                case 3:
+                    errstr = "illegal CPUID value (must be: [0|1|x|k|s])";
+                    break;
+                default:
+                    errstr = "unknown error";
+                    break;
+                }
+                fprintf(stderr, "while parsing CPUID flag: \"%s\":\n", p);
+                fprintf(stderr, "  error #%i: %s\n", e, errstr);
+            }
+            free(buf2);
+        }
+        break;
+    default:
+        break;
+    }
+
+    /* parse device model arguments, this works for pv, hvm and stubdom */
+    if (!xlu_cfg_get_string (config, "device_model", &buf, 0)) {
+        fprintf(stderr,
+                "WARNING: ignoring device_model directive.\n"
+                "WARNING: Use \"device_model_override\" instead if you"
+                " really want a non-default device_model\n");
+        if (strstr(buf, "stubdom-dm")) {
+            if (c_info->type == LIBXL_DOMAIN_TYPE_HVM)
+                fprintf(stderr, "WARNING: Or use"
+                        " \"device_model_stubdomain_override\" if you "
+                        " want to enable stubdomains\n");
+            else
+                fprintf(stderr, "WARNING: ignoring"
+                        " \"device_model_stubdomain_override\" directive"
+                        " for pv guest\n");
+        }
+    }
+
+
+    xlu_cfg_replace_string (config, "device_model_override",
+                            &b_info->device_model, 0);
+    if (!xlu_cfg_get_string (config, "device_model_version", &buf, 0)) {
+        if (!strcmp(buf, "qemu-xen-traditional")) {
+            b_info->device_model_version
+                = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL;
+        } else if (!strcmp(buf, "qemu-xen")) {
+            b_info->device_model_version
+                = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN;
+        } else if (!strcmp(buf, "none")) {
+            b_info->device_model_version = LIBXL_DEVICE_MODEL_VERSION_NONE;
+        } else {
+            fprintf(stderr,
+                    "Unknown device_model_version \"%s\" specified\n", buf);
+            exit(1);
+        }
+    } else if (b_info->device_model)
+        fprintf(stderr, "WARNING: device model override given without specific DM version\n");
+    xlu_cfg_get_defbool (config, "device_model_stubdomain_override",
+                         &b_info->device_model_stubdomain, 0);
+
+    if (!xlu_cfg_get_string (config, "device_model_stubdomain_seclabel",
+                             &buf, 0))
+        xlu_cfg_replace_string(config, "device_model_stubdomain_seclabel",
+                               &b_info->device_model_ssid_label, 0);
+
+    xlu_cfg_replace_string(config, "device_model_user",
+                           &b_info->device_model_user, 0);
+
+#define parse_extra_args(type)                                            \
+    e = xlu_cfg_get_list_as_string_list(config, "device_model_args"#type, \
+                                    &b_info->extra##type, 0);            \
+    if (e && e != ESRCH) {                                                \
+        fprintf(stderr,"xl: Unable to parse device_model_args"#type".\n");\
+        exit(-ERROR_FAIL);                                                \
+    }
+
+    /* parse extra args for qemu, common to both pv, hvm */
+    parse_extra_args();
+
+    /* parse extra args dedicated to pv */
+    parse_extra_args(_pv);
+
+    /* parse extra args dedicated to hvm */
+    parse_extra_args(_hvm);
+
+#undef parse_extra_args
+
+    /* If we've already got vfb=[] for PV guest then ignore top level
+     * VNC config. */
+    if (c_info->type == LIBXL_DOMAIN_TYPE_PV && !d_config->num_vfbs) {
+        long vnc_enabled = 0;
+
+        if (!xlu_cfg_get_long (config, "vnc", &l, 0))
+            vnc_enabled = l;
+
+        if (vnc_enabled) {
+            libxl_device_vfb *vfb;
+            libxl_device_vkb *vkb;
+
+            vfb = ARRAY_EXTEND_INIT(d_config->vfbs, d_config->num_vfbs,
+                                    libxl_device_vfb_init);
+
+            vkb = ARRAY_EXTEND_INIT(d_config->vkbs, d_config->num_vkbs,
+                                    libxl_device_vkb_init);
+
+            parse_top_level_vnc_options(config, &vfb->vnc);
+            parse_top_level_sdl_options(config, &vfb->sdl);
+            xlu_cfg_replace_string (config, "keymap", &vfb->keymap, 0);
+        }
+    } else {
+        parse_top_level_vnc_options(config, &b_info->u.hvm.vnc);
+        parse_top_level_sdl_options(config, &b_info->u.hvm.sdl);
+    }
+
+    if (c_info->type == LIBXL_DOMAIN_TYPE_HVM) {
+        if (!xlu_cfg_get_string (config, "vga", &buf, 0)) {
+            if (!strcmp(buf, "stdvga")) {
+                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_STD;
+            } else if (!strcmp(buf, "cirrus")) {
+                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
+            } else if (!strcmp(buf, "none")) {
+                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_NONE;
+            } else if (!strcmp(buf, "qxl")) {
+                b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_QXL;
+            } else {
+                fprintf(stderr, "Unknown vga \"%s\" specified\n", buf);
+                exit(1);
+            }
+        } else if (!xlu_cfg_get_long(config, "stdvga", &l, 0))
+            b_info->u.hvm.vga.kind = l ? LIBXL_VGA_INTERFACE_TYPE_STD :
+                                         LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
+
+        if (!xlu_cfg_get_string(config, "hdtype", &buf, 0) &&
+            libxl_hdtype_from_string(buf, &b_info->u.hvm.hdtype)) {
+                fprintf(stderr, "ERROR: invalid value \"%s\" for \"hdtype\"\n",
+                    buf);
+                exit (1);
+        }
+
+        xlu_cfg_replace_string (config, "keymap", &b_info->u.hvm.keymap, 0);
+        xlu_cfg_get_defbool (config, "spice", &b_info->u.hvm.spice.enable, 0);
+        if (!xlu_cfg_get_long (config, "spiceport", &l, 0))
+            b_info->u.hvm.spice.port = l;
+        if (!xlu_cfg_get_long (config, "spicetls_port", &l, 0))
+            b_info->u.hvm.spice.tls_port = l;
+        xlu_cfg_replace_string (config, "spicehost",
+                                &b_info->u.hvm.spice.host, 0);
+        xlu_cfg_get_defbool(config, "spicedisable_ticketing",
+                            &b_info->u.hvm.spice.disable_ticketing, 0);
+        xlu_cfg_replace_string (config, "spicepasswd",
+                                &b_info->u.hvm.spice.passwd, 0);
+        xlu_cfg_get_defbool(config, "spiceagent_mouse",
+                            &b_info->u.hvm.spice.agent_mouse, 0);
+        xlu_cfg_get_defbool(config, "spicevdagent",
+                            &b_info->u.hvm.spice.vdagent, 0);
+        xlu_cfg_get_defbool(config, "spice_clipboard_sharing",
+                            &b_info->u.hvm.spice.clipboard_sharing, 0);
+        if (!xlu_cfg_get_long (config, "spiceusbredirection", &l, 0))
+            b_info->u.hvm.spice.usbredirection = l;
+        xlu_cfg_replace_string (config, "spice_image_compression",
+                                &b_info->u.hvm.spice.image_compression, 0);
+        xlu_cfg_replace_string (config, "spice_streaming_video",
+                                &b_info->u.hvm.spice.streaming_video, 0);
+        xlu_cfg_get_defbool(config, "nographic", &b_info->u.hvm.nographic, 0);
+        if (!xlu_cfg_get_long(config, "gfx_passthru", &l, 1)) {
+            libxl_defbool_set(&b_info->u.hvm.gfx_passthru, l);
+        } else if (!xlu_cfg_get_string(config, "gfx_passthru", &buf, 0)) {
+            if (libxl_gfx_passthru_kind_from_string(buf,
+                                        &b_info->u.hvm.gfx_passthru_kind)) {
+                fprintf(stderr,
+                        "ERROR: invalid value \"%s\" for \"gfx_passthru\"\n",
+                        buf);
+                exit (1);
+            }
+            libxl_defbool_set(&b_info->u.hvm.gfx_passthru, true);
+        }
+        switch (xlu_cfg_get_list_as_string_list(config, "serial",
+                                                &b_info->u.hvm.serial_list,
+                                                1))
+        {
+
+        case 0: break; /* Success */
+        case ESRCH: break; /* Option not present */
+        case EINVAL:
+            /* If it's not a valid list, try reading it as an atom,
+             * falling through to an error if it fails */
+            if (!xlu_cfg_replace_string(config, "serial",
+                                        &b_info->u.hvm.serial, 0))
+                break;
+            /* FALLTHRU */
+        default:
+            fprintf(stderr,"xl: Unable to parse serial.\n");
+            exit(-ERROR_FAIL);
+        }
+        xlu_cfg_replace_string (config, "boot", &b_info->u.hvm.boot, 0);
+        xlu_cfg_get_defbool(config, "usb", &b_info->u.hvm.usb, 0);
+        if (!xlu_cfg_get_long (config, "usbversion", &l, 0))
+            b_info->u.hvm.usbversion = l;
+        switch (xlu_cfg_get_list_as_string_list(config, "usbdevice",
+                                                &b_info->u.hvm.usbdevice_list,
+                                                1))
+        {
+
+        case 0: break; /* Success */
+        case ESRCH: break; /* Option not present */
+        case EINVAL:
+            /* If it's not a valid list, try reading it as an atom,
+             * falling through to an error if it fails */
+            if (!xlu_cfg_replace_string(config, "usbdevice",
+                                        &b_info->u.hvm.usbdevice, 0))
+                break;
+            /* FALLTHRU */
+        default:
+            fprintf(stderr,"xl: Unable to parse usbdevice.\n");
+            exit(-ERROR_FAIL);
+        }
+        xlu_cfg_replace_string (config, "soundhw", &b_info->u.hvm.soundhw, 0);
+        xlu_cfg_get_defbool(config, "xen_platform_pci",
+                            &b_info->u.hvm.xen_platform_pci, 0);
+
+        if(b_info->u.hvm.vnc.listen
+           && b_info->u.hvm.vnc.display
+           && strchr(b_info->u.hvm.vnc.listen, ':') != NULL) {
+            fprintf(stderr,
+                    "ERROR: Display specified both in vnclisten"
+                    " and vncdisplay!\n");
+            exit (1);
+
+        }
+
+        if (!xlu_cfg_get_string (config, "vendor_device", &buf, 0)) {
+            libxl_vendor_device d;
+
+            e = libxl_vendor_device_from_string(buf, &d);
+            if (e) {
+                fprintf(stderr,
+                        "xl: unknown vendor_device '%s'\n",
+                        buf);
+                exit(-ERROR_FAIL);
+            }
+
+            b_info->u.hvm.vendor_device = d;
+        }
+    }
+
+    if (!xlu_cfg_get_string (config, "gic_version", &buf, 1)) {
+        e = libxl_gic_version_from_string(buf, &b_info->arch_arm.gic_version);
+        if (e) {
+            fprintf(stderr,
+                    "Unknown gic_version \"%s\" specified\n", buf);
+            exit(-ERROR_FAIL);
+        }
+     }
+
+    xlu_cfg_destroy(config);
+}
+
+/* Returns -1 on failure; the amount of memory on success. */
+int64_t parse_mem_size_kb(const char *mem)
+{
+    char *endptr;
+    int64_t kbytes;
+
+    kbytes = strtoll(mem, &endptr, 10);
+
+    if (strlen(endptr) > 1)
+        return -1;
+
+    switch (tolower((uint8_t)*endptr)) {
+    case 't':
+        kbytes <<= 10;
+        /* fallthrough */
+    case 'g':
+        kbytes <<= 10;
+        /* fallthrough */
+    case '\0':
+    case 'm':
+        kbytes <<= 10;
+        /* fallthrough */
+    case 'k':
+        break;
+    case 'b':
+        kbytes >>= 10;
+        break;
+    default:
+        return -1;
+    }
+
+    return kbytes;
+}
+
+
+void split_string_into_string_list(const char *str,
+                                   const char *delim,
+                                   libxl_string_list *psl)
+{
+    char *s, *saveptr;
+    const char *p;
+    libxl_string_list sl;
+
+    int i = 0, nr = 0;
+
+    s = strdup(str);
+    if (s == NULL) {
+        fprintf(stderr, "unable to allocate memory to split string\n");
+        exit(-1);
+    }
+
+    /* Count number of entries */
+    p = strtok_r(s, delim, &saveptr);
+    do {
+        nr++;
+    } while ((p = strtok_r(NULL, delim, &saveptr)));
+
+    free(s);
+
+    s = strdup(str);
+
+    sl = malloc((nr+1) * sizeof (char *));
+    if (sl == NULL) {
+        fprintf(stderr, "unable to allocate memory to split string\n");
+        exit(-1);
+    }
+
+    p = strtok_r(s, delim, &saveptr);
+    do {
+        assert(i < nr);
+        sl[i] = strdup(p);
+        i++;
+    } while ((p = strtok_r(NULL, delim, &saveptr)));
+    sl[i] = NULL;
+
+    *psl = sl;
+
+    free(s);
+}
+
+void trim(char_predicate_t predicate, const char *input, char **output)
+{
+    const char *first, *after;
+
+    for (first = input;
+         *first && predicate((unsigned char)first[0]);
+         first++)
+        ;
+
+    for (after = first + strlen(first);
+         after > first && predicate((unsigned char)after[-1]);
+         after--)
+        ;
+
+    size_t len_nonnull = after - first;
+    char *result = xmalloc(len_nonnull + 1);
+
+    memcpy(result, first, len_nonnull);
+    result[len_nonnull] = 0;
+
+    *output = result;
+}
+
+int split_string_into_pair(const char *str,
+                           const char *delim,
+                           char **a,
+                           char **b)
+{
+    char *s, *p, *saveptr, *aa = NULL, *bb = NULL;
+    int rc = 0;
+
+    s = xstrdup(str);
+
+    p = strtok_r(s, delim, &saveptr);
+    if (p == NULL) {
+        rc = ERROR_INVAL;
+        goto out;
+    }
+    aa = xstrdup(p);
+    p = strtok_r(NULL, delim, &saveptr);
+    if (p == NULL) {
+        rc = ERROR_INVAL;
+        goto out;
+    }
+    bb = xstrdup(p);
+
+    *a = aa;
+    aa = NULL;
+    *b = bb;
+    bb = NULL;
+out:
+    free(s);
+    free(aa);
+    free(bb);
+    return rc;
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/xl/xl_parse.h b/tools/xl/xl_parse.h
new file mode 100644
index 0000000000..db8bc3f051
--- /dev/null
+++ b/tools/xl/xl_parse.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#ifndef XL_PARSE_H
+#define XL_PARSE_H
+
+#include <libxl.h>
+
+void parse_config_data(const char *config_source,
+                       const char *config_data,
+                       int config_len,
+                       libxl_domain_config *d_config);
+int parse_range(const char *str, unsigned long *a, unsigned long *b);
+int64_t parse_mem_size_kb(const char *mem);
+void parse_disk_config(XLU_Config **config, const char *spec,
+                       libxl_device_disk *disk);
+
+void parse_disk_config_multistring(XLU_Config **config,
+                                   int nspecs, const char *const *specs,
+                                   libxl_device_disk *disk);
+int parse_usbctrl_config(libxl_device_usbctrl *usbctrl, char *token);
+int parse_usbdev_config(libxl_device_usbdev *usbdev, char *token);
+int parse_cpurange(const char *cpu, libxl_bitmap *cpumap);
+int parse_nic_config(libxl_device_nic *nic, XLU_Config **config, char *token);
+
+
+int match_option_size(const char *prefix, size_t len,
+                      char *arg, char **argopt);
+#define MATCH_OPTION(prefix, arg, oparg) \
+    match_option_size((prefix "="), sizeof((prefix)), (arg), &(oparg))
+
+
+void split_string_into_string_list(const char *str, const char *delim,
+                                   libxl_string_list *psl);
+int split_string_into_pair(const char *str, const char *delim,
+                           char **a, char **b);
+void replace_string(char **str, const char *val);
+
+/* NB: this follows the interface used by <ctype.h>. See 'man 3 ctype'
+   and look for CTYPE in libxl_internal.h */
+typedef int (*char_predicate_t)(const int c);
+void trim(char_predicate_t predicate, const char *input, char **output);
+
+const char *get_action_on_shutdown_name(libxl_action_on_shutdown a);
+
+#endif	/* XL_PARSE_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 1/2] xl: call libxl_vncviewer_exec in main_vncviewer
  2017-02-27 15:59   ` Ian Jackson
@ 2017-02-27 17:48     ` Wei Liu
  2017-02-27 17:48       ` [PATCH 2/2] xl: split out vnc and console related code Wei Liu
  2017-02-27 18:12       ` [PATCH 1/2] xl: call libxl_vncviewer_exec in main_vncviewer Ian Jackson
  0 siblings, 2 replies; 76+ messages in thread
From: Wei Liu @ 2017-02-27 17:48 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

We will need to move main_vncviewer to a different file where it has no
access to the helper vncviewer.

Call libxl_vncviewer_exec directly.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/xl_cmdimpl.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index 26fd4ab0f5..a42b972d60 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -1120,9 +1120,10 @@ int main_vncviewer(int argc, char **argv)
 
     domid = find_domain(argv[optind]);
 
-    if (vncviewer(domid, autopass))
-        return EXIT_FAILURE;
-    return EXIT_SUCCESS;
+    libxl_vncviewer_exec(ctx, domid, autopass);
+    fprintf(stderr, "Unable to execute vncviewer\n");
+
+    return EXIT_FAILURE;
 }
 
 static void pause_domain(uint32_t domid)
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 2/2] xl: split out vnc and console related code
  2017-02-27 17:48     ` [PATCH 1/2] xl: call libxl_vncviewer_exec in main_vncviewer Wei Liu
@ 2017-02-27 17:48       ` Wei Liu
  2017-02-27 18:13         ` Ian Jackson
  2017-02-27 18:12       ` [PATCH 1/2] xl: call libxl_vncviewer_exec in main_vncviewer Ian Jackson
  1 sibling, 1 reply; 76+ messages in thread
From: Wei Liu @ 2017-02-27 17:48 UTC (permalink / raw)
  To: Xen-devel; +Cc: Wei Liu, Ian Jackson

The new file also contains code for channel, which is just a console
in disguise.

Replace the call to vncviewer() with libxl_vncviewer_exec() directly in
main_vncviewer.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/xl/Makefile     |   2 +-
 tools/xl/xl_cmdimpl.c |  99 --------------------------------------
 tools/xl/xl_console.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 131 insertions(+), 100 deletions(-)
 create mode 100644 tools/xl/xl_console.c

diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index bc8cfb3de9..7375d2bfda 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -19,7 +19,7 @@ XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
 XL_OBJS += xl_tmem.o xl_parse.o xl_cpupool.o xl_flask.o
 XL_OBJS += xl_vtpm.o xl_block.o xl_nic.o xl_usb.o
 XL_OBJS += xl_sched.o xl_pci.o xl_vcpu.o xl_cdrom.o xl_mem.o
-XL_OBJS += xl_psr.o xl_info.o
+XL_OBJS += xl_psr.o xl_info.o xl_console.o
 
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index a42b972d60..958058cadb 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -1071,61 +1071,6 @@ void help(const char *command)
     }
 }
 
-int main_console(int argc, char **argv)
-{
-    uint32_t domid;
-    int opt = 0, num = 0;
-    libxl_console_type type = 0;
-
-    SWITCH_FOREACH_OPT(opt, "n:t:", NULL, "console", 1) {
-    case 't':
-        if (!strcmp(optarg, "pv"))
-            type = LIBXL_CONSOLE_TYPE_PV;
-        else if (!strcmp(optarg, "serial"))
-            type = LIBXL_CONSOLE_TYPE_SERIAL;
-        else {
-            fprintf(stderr, "console type supported are: pv, serial\n");
-            return EXIT_FAILURE;
-        }
-        break;
-    case 'n':
-        num = atoi(optarg);
-        break;
-    }
-
-    domid = find_domain(argv[optind]);
-    if (!type)
-        libxl_primary_console_exec(ctx, domid, -1);
-    else
-        libxl_console_exec(ctx, domid, num, type, -1);
-    fprintf(stderr, "Unable to attach console\n");
-    return EXIT_FAILURE;
-}
-
-int main_vncviewer(int argc, char **argv)
-{
-    static const struct option opts[] = {
-        {"autopass", 0, 0, 'a'},
-        {"vncviewer-autopass", 0, 0, 'a'},
-        COMMON_LONG_OPTS
-    };
-    uint32_t domid;
-    int opt, autopass = 0;
-
-    SWITCH_FOREACH_OPT(opt, "a", opts, "vncviewer", 1) {
-    case 'a':
-        autopass = 1;
-        break;
-    }
-
-    domid = find_domain(argv[optind]);
-
-    libxl_vncviewer_exec(ctx, domid, autopass);
-    fprintf(stderr, "Unable to execute vncviewer\n");
-
-    return EXIT_FAILURE;
-}
-
 static void pause_domain(uint32_t domid)
 {
     libxl_domain_pause(ctx, domid);
@@ -2515,50 +2460,6 @@ int main_debug_keys(int argc, char **argv)
     return EXIT_SUCCESS;
 }
 
-int main_channellist(int argc, char **argv)
-{
-    int opt;
-    libxl_device_channel *channels;
-    libxl_channelinfo channelinfo;
-    int nb, i;
-
-    SWITCH_FOREACH_OPT(opt, "", NULL, "channel-list", 1) {
-        /* No options */
-    }
-
-    /*      Idx BE state evt-ch ring-ref connection params*/
-    printf("%-3s %-2s %-5s %-6s %8s %-10s %-30s\n",
-           "Idx", "BE", "state", "evt-ch", "ring-ref", "connection", "");
-    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
-        uint32_t domid = find_domain(*argv);
-        channels = libxl_device_channel_list(ctx, domid, &nb);
-        if (!channels)
-            continue;
-        for (i = 0; i < nb; ++i) {
-            if (!libxl_device_channel_getinfo(ctx, domid, &channels[i],
-                &channelinfo)) {
-                printf("%-3d %-2d ", channels[i].devid, channelinfo.backend_id);
-                printf("%-5d ", channelinfo.state);
-                printf("%-6d %-8d ", channelinfo.evtch, channelinfo.rref);
-                printf("%-10s ", libxl_channel_connection_to_string(
-                       channels[i].connection));
-                switch (channels[i].connection) {
-                    case LIBXL_CHANNEL_CONNECTION_PTY:
-                        printf("%-30s ", channelinfo.u.pty.path);
-                        break;
-                    default:
-                        break;
-                }
-                printf("\n");
-                libxl_channelinfo_dispose(&channelinfo);
-            }
-            libxl_device_channel_dispose(&channels[i]);
-        }
-        free(channels);
-    }
-    return 0;
-}
-
 #ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
 int main_remus(int argc, char **argv)
 {
diff --git a/tools/xl/xl_console.c b/tools/xl/xl_console.c
new file mode 100644
index 0000000000..0508ddaa32
--- /dev/null
+++ b/tools/xl/xl_console.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include <stdlib.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+int main_console(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt = 0, num = 0;
+    libxl_console_type type = 0;
+
+    SWITCH_FOREACH_OPT(opt, "n:t:", NULL, "console", 1) {
+    case 't':
+        if (!strcmp(optarg, "pv"))
+            type = LIBXL_CONSOLE_TYPE_PV;
+        else if (!strcmp(optarg, "serial"))
+            type = LIBXL_CONSOLE_TYPE_SERIAL;
+        else {
+            fprintf(stderr, "console type supported are: pv, serial\n");
+            return EXIT_FAILURE;
+        }
+        break;
+    case 'n':
+        num = atoi(optarg);
+        break;
+    }
+
+    domid = find_domain(argv[optind]);
+    if (!type)
+        libxl_primary_console_exec(ctx, domid, -1);
+    else
+        libxl_console_exec(ctx, domid, num, type, -1);
+    fprintf(stderr, "Unable to attach console\n");
+    return EXIT_FAILURE;
+}
+
+int main_vncviewer(int argc, char **argv)
+{
+    static const struct option opts[] = {
+        {"autopass", 0, 0, 'a'},
+        {"vncviewer-autopass", 0, 0, 'a'},
+        COMMON_LONG_OPTS
+    };
+    uint32_t domid;
+    int opt, autopass = 0;
+
+    SWITCH_FOREACH_OPT(opt, "a", opts, "vncviewer", 1) {
+    case 'a':
+        autopass = 1;
+        break;
+    }
+
+    domid = find_domain(argv[optind]);
+
+    libxl_vncviewer_exec(ctx, domid, autopass);
+
+    return EXIT_FAILURE;
+}
+
+/* Channel is just a console in disguise, so put it here */
+int main_channellist(int argc, char **argv)
+{
+    int opt;
+    libxl_device_channel *channels;
+    libxl_channelinfo channelinfo;
+    int nb, i;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "channel-list", 1) {
+        /* No options */
+    }
+
+    /*      Idx BE state evt-ch ring-ref connection params*/
+    printf("%-3s %-2s %-5s %-6s %8s %-10s %-30s\n",
+           "Idx", "BE", "state", "evt-ch", "ring-ref", "connection", "");
+    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
+        uint32_t domid = find_domain(*argv);
+        channels = libxl_device_channel_list(ctx, domid, &nb);
+        if (!channels)
+            continue;
+        for (i = 0; i < nb; ++i) {
+            if (!libxl_device_channel_getinfo(ctx, domid, &channels[i],
+                &channelinfo)) {
+                printf("%-3d %-2d ", channels[i].devid, channelinfo.backend_id);
+                printf("%-5d ", channelinfo.state);
+                printf("%-6d %-8d ", channelinfo.evtch, channelinfo.rref);
+                printf("%-10s ", libxl_channel_connection_to_string(
+                       channels[i].connection));
+                switch (channels[i].connection) {
+                    case LIBXL_CHANNEL_CONNECTION_PTY:
+                        printf("%-30s ", channelinfo.u.pty.path);
+                        break;
+                    default:
+                        break;
+                }
+                printf("\n");
+                libxl_channelinfo_dispose(&channelinfo);
+            }
+            libxl_device_channel_dispose(&channels[i]);
+        }
+        free(channels);
+    }
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* Re: [PATCH 2/3] xl: introduce a function to get shutdown action name
  2017-02-27 17:47       ` [PATCH 2/3] xl: introduce a function to get shutdown action name Wei Liu
@ 2017-02-27 18:11         ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 18:11 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 2/3] xl: introduce a function to get shutdown action name"):
> The array to map libxl_shutdown_action_to_shutdown to string is going to
> be moved to a dedicated file.

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 1/3] xl: rename cpurange_parse to parse_cpurange
  2017-02-27 17:47     ` [PATCH 1/3] xl: rename cpurange_parse to parse_cpurange Wei Liu
  2017-02-27 17:47       ` [PATCH 2/3] xl: introduce a function to get shutdown action name Wei Liu
  2017-02-27 17:47       ` [PATCH 3/3] xl: split out xl_parse.[ch] Wei Liu
@ 2017-02-27 18:11       ` Ian Jackson
  2 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 18:11 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 1/3] xl: rename cpurange_parse to parse_cpurange"):
> We want to consistently prefix functions to parse input with "parse_".

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 3/3] xl: split out xl_parse.[ch]
  2017-02-27 17:47       ` [PATCH 3/3] xl: split out xl_parse.[ch] Wei Liu
@ 2017-02-27 18:11         ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 18:11 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 3/3] xl: split out xl_parse.[ch]"):
> Move all parsing code into xl_parse.c. Export the ones needed in
> xl_parse.h.

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 1/2] xl: call libxl_vncviewer_exec in main_vncviewer
  2017-02-27 17:48     ` [PATCH 1/2] xl: call libxl_vncviewer_exec in main_vncviewer Wei Liu
  2017-02-27 17:48       ` [PATCH 2/2] xl: split out vnc and console related code Wei Liu
@ 2017-02-27 18:12       ` Ian Jackson
  1 sibling, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 18:12 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 1/2] xl: call libxl_vncviewer_exec in main_vncviewer"):
> We will need to move main_vncviewer to a different file where it has no
> access to the helper vncviewer.

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 2/2] xl: split out vnc and console related code
  2017-02-27 17:48       ` [PATCH 2/2] xl: split out vnc and console related code Wei Liu
@ 2017-02-27 18:13         ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-27 18:13 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH 2/2] xl: split out vnc and console related code"):
> The new file also contains code for channel, which is just a console
> in disguise.

Good.  Except that...

> Replace the call to vncviewer() with libxl_vncviewer_exec() directly in
> main_vncviewer.

... you forgot to remove this from the commit message.

With that change,

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

Ian.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH] xl: move some helper functions to xl_utils.c
  2017-02-27 17:44     ` [PATCH] " Wei Liu
@ 2017-02-28 10:32       ` Ian Jackson
  0 siblings, 0 replies; 76+ messages in thread
From: Ian Jackson @ 2017-02-28 10:32 UTC (permalink / raw)
  To: Wei Liu; +Cc: Xen-devel

Wei Liu writes ("[PATCH] xl: move some helper functions to xl_utils.c"):
> Move some commonly used functions to a new file.

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

end of thread, other threads:[~2017-02-28 10:32 UTC | newest]

Thread overview: 76+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-24 16:12 [PATCH 00/29] Refactor xl code Wei Liu
2017-02-24 16:12 ` [PATCH 01/29] xl: remove accidentally committed hunk from Makefile Wei Liu
2017-02-27 15:53   ` Ian Jackson
2017-02-24 16:12 ` [PATCH 02/29] xl: update copyright information Wei Liu
2017-02-27 15:54   ` Ian Jackson
2017-02-24 16:12 ` [PATCH 03/29] xl: remove inclusion of libxl_osdeps.h Wei Liu
2017-02-27 15:53   ` Ian Jackson
2017-02-24 16:12 ` [PATCH 04/29] xl: use <> variant to include Xen tools library headers Wei Liu
2017-02-27 15:54   ` Ian Jackson
2017-02-24 16:12 ` [PATCH 05/29] xl: generate _paths.h Wei Liu
2017-02-27 15:54   ` Ian Jackson
2017-02-24 16:12 ` [PATCH 06/29] xl: remove trailing spaces in xl_cmdimpl.c Wei Liu
2017-02-27 15:54   ` Ian Jackson
2017-02-24 16:12 ` [PATCH 07/29] xl: lift a bunch of macros to xl_utils.h Wei Liu
2017-02-27 15:54   ` Ian Jackson
2017-02-24 16:12 ` [PATCH 08/29] xl: move some helper functions to xl_utils.c Wei Liu
2017-02-27 15:53   ` Ian Jackson
2017-02-27 17:44     ` [PATCH] " Wei Liu
2017-02-28 10:32       ` Ian Jackson
2017-02-24 16:12 ` [PATCH 09/29] xl: split out tmem related code to xl_tmem.c Wei Liu
2017-02-27 15:54   ` Ian Jackson
2017-02-24 16:12 ` [PATCH 10/29] xl: split out xl_parse.[ch] Wei Liu
2017-02-27 15:57   ` Ian Jackson
2017-02-27 17:47     ` [PATCH 1/3] xl: rename cpurange_parse to parse_cpurange Wei Liu
2017-02-27 17:47       ` [PATCH 2/3] xl: introduce a function to get shutdown action name Wei Liu
2017-02-27 18:11         ` Ian Jackson
2017-02-27 17:47       ` [PATCH 3/3] xl: split out xl_parse.[ch] Wei Liu
2017-02-27 18:11         ` Ian Jackson
2017-02-27 18:11       ` [PATCH 1/3] xl: rename cpurange_parse to parse_cpurange Ian Jackson
2017-02-24 16:12 ` [PATCH 11/29] xl: split out cpupool related code Wei Liu
2017-02-27 15:59   ` Ian Jackson
2017-02-24 16:12 ` [PATCH 12/29] xl: split out flask " Wei Liu
2017-02-27 16:01   ` Ian Jackson
2017-02-24 16:12 ` [PATCH 13/29] xl: split out vtpm " Wei Liu
2017-02-27 15:55   ` Ian Jackson
2017-02-24 16:12 ` [PATCH 14/29] xl: split out block " Wei Liu
2017-02-27 15:58   ` Ian Jackson
2017-02-24 16:13 ` [PATCH 15/29] xl: split out network " Wei Liu
2017-02-27 16:01   ` Ian Jackson
2017-02-24 16:13 ` [PATCH 16/29] xl: split out usb " Wei Liu
2017-02-27 16:00   ` Ian Jackson
2017-02-24 16:13 ` [PATCH 17/29] xl: split out scheduler " Wei Liu
2017-02-27 15:57   ` Ian Jackson
2017-02-24 16:13 ` [PATCH 18/29] xl: split out pci " Wei Liu
2017-02-27 16:01   ` Ian Jackson
2017-02-24 16:13 ` [PATCH 19/29] xl: split out vcpu " Wei Liu
2017-02-27 15:59   ` Ian Jackson
2017-02-24 16:13 ` [PATCH 20/29] xl: split out cd " Wei Liu
2017-02-27 15:56   ` Ian Jackson
2017-02-27 16:23     ` Wei Liu
2017-02-27 16:36       ` Ian Jackson
2017-02-27 16:38         ` Wei Liu
2017-02-27 16:44           ` Ian Jackson
2017-02-27 16:45             ` Wei Liu
2017-02-24 16:13 ` [PATCH 21/29] xl: split out memory " Wei Liu
2017-02-27 16:01   ` Ian Jackson
2017-02-24 16:13 ` [PATCH 22/29] xl: split out psr " Wei Liu
2017-02-27 15:55   ` Ian Jackson
2017-02-24 16:13 ` [PATCH 23/29] xl: split out functions to print out information Wei Liu
2017-02-27 16:00   ` Ian Jackson
2017-02-24 16:13 ` [PATCH 24/29] xl: split out vnc and console related code Wei Liu
2017-02-27 15:59   ` Ian Jackson
2017-02-27 17:48     ` [PATCH 1/2] xl: call libxl_vncviewer_exec in main_vncviewer Wei Liu
2017-02-27 17:48       ` [PATCH 2/2] xl: split out vnc and console related code Wei Liu
2017-02-27 18:13         ` Ian Jackson
2017-02-27 18:12       ` [PATCH 1/2] xl: call libxl_vncviewer_exec in main_vncviewer Ian Jackson
2017-02-24 16:13 ` [PATCH 25/29] xl: split out miscellaneous functions Wei Liu
2017-02-27 15:58   ` Ian Jackson
2017-02-24 16:13 ` [PATCH 26/29] xl: split out vm lifecycle control functions Wei Liu
2017-02-27 16:00   ` Ian Jackson
2017-02-24 16:13 ` [PATCH 27/29] xl: split out save/restore related code Wei Liu
2017-02-27 16:01   ` Ian Jackson
2017-02-24 16:13 ` [PATCH 28/29] xl: split out migration " Wei Liu
2017-02-27 15:59   ` Ian Jackson
2017-02-24 16:13 ` [PATCH 29/29] xl: merge xl_cmdimpl.c into xl.c Wei Liu
2017-02-27 15:58   ` Ian Jackson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.