WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] merge with xen-unstable.hg

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] merge with xen-unstable.hg
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 23 Feb 2007 09:50:33 -0800
Delivery-date: Fri, 23 Feb 2007 09:51:27 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User awilliam@xxxxxxxxxxxx
# Date 1172164529 25200
# Node ID 202eb735b425d4f99fb8a78ab6df6e7c9b70c6cb
# Parent  9364bea18bc4a2d83923a8ffd1481952e635c80f
# Parent  f62a052384a54a379580a95aa79a70e3fcf86a6d
merge with xen-unstable.hg
---
 docs/xen-api/xenapi-datamodel.tex                  | 2983 ++++++++++++---------
 linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c |    5 
 linux-2.6-xen-sparse/drivers/xen/blkback/common.h  |    2 
 linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c  |   12 
 linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c   |   11 
 linux-2.6-xen-sparse/drivers/xen/blktap/common.h   |    2 
 linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c   |  103 
 tools/libfsimage/Makefile                          |    2 
 tools/libfsimage/common/fsimage_grub.c             |   78 
 tools/libfsimage/common/fsimage_grub.h             |    5 
 tools/libfsimage/common/mapfile-GNU                |    1 
 tools/libfsimage/common/mapfile-SunOS              |    1 
 tools/libfsimage/ext2fs/fsys_ext2fs.c              |   89 
 tools/libfsimage/fat/Makefile                      |   13 
 tools/libfsimage/fat/fat.h                         |  100 
 tools/libfsimage/fat/fsys_fat.c                    |  485 +++
 tools/libfsimage/iso9660/Makefile                  |   15 
 tools/libfsimage/iso9660/fsys_iso9660.c            |  463 +++
 tools/libfsimage/iso9660/iso9660.h                 |  219 +
 tools/libfsimage/reiserfs/fsys_reiserfs.c          |   77 
 tools/libxen/include/xen_console.h                 |   49 
 tools/libxen/include/xen_host.h                    |   25 
 tools/libxen/include/xen_internal.h                |    5 
 tools/libxen/include/xen_string_set.h              |   47 
 tools/libxen/include/xen_vbd.h                     |   89 
 tools/libxen/include/xen_vbd_metrics.h             |  183 +
 tools/libxen/include/xen_vbd_metrics_decl.h        |   30 
 tools/libxen/include/xen_vbd_type.h                |   77 
 tools/libxen/include/xen_vbd_type_internal.h       |   37 
 tools/libxen/include/xen_vif.h                     |   69 
 tools/libxen/include/xen_vif_metrics.h             |  183 +
 tools/libxen/include/xen_vif_metrics_decl.h        |   30 
 tools/libxen/include/xen_vm_metrics.h              |   11 
 tools/libxen/src/xen_common.c                      |    4 
 tools/libxen/src/xen_console.c                     |  106 
 tools/libxen/src/xen_host.c                        |   54 
 tools/libxen/src/xen_string_set.c                  |   47 
 tools/libxen/src/xen_string_set.h                  |   47 
 tools/libxen/src/xen_vbd.c                         |  208 +
 tools/libxen/src/xen_vbd_metrics.c                 |  150 +
 tools/libxen/src/xen_vbd_type.c                    |   81 
 tools/libxen/src/xen_vif.c                         |  161 -
 tools/libxen/src/xen_vif_metrics.c                 |  150 +
 tools/libxen/src/xen_vm_metrics.c                  |   24 
 tools/libxen/test/test_bindings.c                  |   79 
 tools/python/xen/xend/XendAPI.py                   |  214 -
 tools/python/xen/xm/messages/en/xen-xm.po          |   42 
 tools/tests/test_x86_emulator.c                    |   48 
 xen/acm/acm_chinesewall_hooks.c                    |   15 
 xen/acm/acm_simple_type_enforcement_hooks.c        |   76 
 xen/arch/ia64/linux-xen/mca.c                      |    2 
 xen/arch/ia64/linux-xen/perfmon.c                  |   12 
 xen/arch/powerpc/audit.c                           |    2 
 xen/arch/x86/domctl.c                              |   36 
 xen/arch/x86/extable.c                             |   13 
 xen/arch/x86/hvm/io.c                              |    2 
 xen/arch/x86/hvm/platform.c                        |    1 
 xen/arch/x86/hvm/svm/vmcb.c                        |    5 
 xen/arch/x86/hvm/vmx/vmcs.c                        |    5 
 xen/arch/x86/hvm/vmx/vmx.c                         |    2 
 xen/arch/x86/mm.c                                  |   17 
 xen/arch/x86/mm/shadow/common.c                    |   20 
 xen/arch/x86/mm/shadow/multi.c                     |   24 
 xen/arch/x86/time.c                                |    4 
 xen/arch/x86/traps.c                               |  101 
 xen/arch/x86/x86_32/entry.S                        |    4 
 xen/arch/x86/x86_64/entry.S                        |    4 
 xen/arch/x86/x86_emulate.c                         |   16 
 xen/common/domain.c                                |   96 
 xen/common/domctl.c                                |   11 
 xen/common/keyhandler.c                            |    4 
 xen/common/sched_sedf.c                            |    8 
 xen/common/sysctl.c                                |    4 
 xen/include/asm-x86/bug.h                          |   12 
 xen/include/asm-x86/event.h                        |    7 
 xen/include/asm-x86/x86_32/bug.h                   |   27 
 xen/include/asm-x86/x86_64/bug.h                   |   27 
 xen/include/asm-x86/x86_emulate.h                  |   24 
 xen/include/xen/lib.h                              |   22 
 xen/include/xen/rcupdate.h                         |   53 
 xen/include/xen/sched.h                            |   32 
 81 files changed, 5621 insertions(+), 1983 deletions(-)

diff -r 9364bea18bc4 -r 202eb735b425 docs/xen-api/xenapi-datamodel.tex
--- a/docs/xen-api/xenapi-datamodel.tex Thu Feb 22 09:42:13 2007 -0700
+++ b/docs/xen-api/xenapi-datamodel.tex Thu Feb 22 10:15:29 2007 -0700
@@ -31,11 +31,13 @@ Name & Description \\
 {\tt host\_cpu} & A physical CPU \\
 {\tt network} & A virtual network \\
 {\tt VIF} & A virtual network interface \\
+{\tt VIF\_metrics} & The metrics associated with a virtual network device \\
 {\tt PIF} & A physical network interface (note separate VLANs are represented 
as several PIFs) \\
 {\tt PIF\_metrics} & The metrics associated with a physical network interface 
\\
 {\tt SR} & A storage repository \\
 {\tt VDI} & A virtual disk image \\
 {\tt VBD} & A virtual block device \\
+{\tt VBD\_metrics} & The metrics associated with a virtual block device \\
 {\tt PBD} & The physical block devices through which hosts access SRs \\
 {\tt crashdump} & A VM crashdump \\
 {\tt VTPM} & A virtual TPM device \\
@@ -61,7 +63,6 @@ VIF.network & network.VIFs & one-to-many
 VIF.network & network.VIFs & one-to-many\\
 host.metrics & host\_metrics.host & one-to-one\\
 PIF.metrics & PIF\_metrics.PIF & one-to-one\\
-VM.metrics & VM\_metrics.VM & one-to-one\\
 PIF.host & host.PIFs & one-to-many\\
 PIF.network & network.PIFs & one-to-many\\
 SR.VDIs & VDI.SR & many-to-one\\
@@ -1076,8 +1077,6 @@ Quals & Field & Type & Description \\
 $\mathit{RW}$ &  {\tt VCPUs/params} & (string $\rightarrow$ string) Map & 
configuration parameters for the selected VCPU policy \\
 $\mathit{RW}$ &  {\tt VCPUs/max} & int & Max number of VCPUs \\
 $\mathit{RW}$ &  {\tt VCPUs/at\_startup} & int & Boot number of VCPUs \\
-$\mathit{RO}_\mathit{ins}$ &  {\tt VCPUs/number} & int & Current number of 
VCPUs \\
-$\mathit{RO}_\mathit{run}$ &  {\tt VCPUs/utilisation} & (int $\rightarrow$ 
float) Map & Utilisation for all of guest's current VCPUs \\
 $\mathit{RW}$ &  {\tt actions/after\_shutdown} & on\_normal\_exit & action to 
take after the guest has shutdown itself \\
 $\mathit{RW}$ &  {\tt actions/after\_reboot} & on\_normal\_exit & action to 
take after the guest has rebooted itself \\
 $\mathit{RW}$ &  {\tt actions/after\_crash} & on\_crash\_behaviour & action to 
take if the guest crashes \\
@@ -1102,7 +1101,7 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt tools\_version} & (string $\rightarrow$ 
string) Map & versions of installed paravirtualised drivers \\
 $\mathit{RW}$ &  {\tt other\_config} & (string $\rightarrow$ string) Map & 
additional configuration \\
 $\mathit{RO}_\mathit{run}$ &  {\tt is\_control\_domain} & bool & true if this 
is a control domain (domain 0 or a driver domain) \\
-$\mathit{RO}_\mathit{ins}$ &  {\tt metrics} & VM\_metrics ref & metrics 
associated with this VM. \\
+$\mathit{RO}_\mathit{run}$ &  {\tt metrics} & VM\_metrics ref & metrics 
associated with this VM. \\
 \hline
 \end{longtable}
 \subsection{Additional RPCs associated with class: VM}
@@ -2545,70 +2544,6 @@ void
 
 
 
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_VCPUs\_number}
-
-{\bf Overview:} 
-Get the VCPUs/number field of the given VM.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} int get_VCPUs_number (session_id s, VM ref self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VM ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-int
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_VCPUs\_utilisation}
-
-{\bf Overview:} 
-Get the VCPUs/utilisation field of the given VM.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} ((int -> float) Map) get_VCPUs_utilisation (session_id s, VM 
ref self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VM ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-(int $\rightarrow$ float) Map
-}
-
-
-value of the field
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
@@ -4273,7 +4208,6 @@ Quals & Field & Type & Description \\
 Quals & Field & Type & Description \\
 \hline
 $\mathit{RO}_\mathit{run}$ &  {\tt uuid} & string & unique identifier/object 
reference \\
-$\mathit{RO}_\mathit{ins}$ &  {\tt VM} & VM ref & VM to which these metrics 
apply \\
 $\mathit{RO}_\mathit{run}$ &  {\tt memory/actual} & int & Guest's actual 
memory (bytes) \\
 $\mathit{RO}_\mathit{run}$ &  {\tt VCPUs/number} & int & Current number of 
VCPUs \\
 $\mathit{RO}_\mathit{run}$ &  {\tt VCPUs/utilisation} & (int $\rightarrow$ 
float) Map & Utilisation for all of guest's current VCPUs \\
@@ -4305,38 +4239,6 @@ Get the uuid field of the given VM\_metr
  \noindent {\bf Return Type:} 
 {\tt 
 string
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_VM}
-
-{\bf Overview:} 
-Get the VM field of the given VM\_metrics.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} (VM ref) get_VM (session_id s, VM_metrics ref 
self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VM\_metrics ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-VM ref
 }
 
 
@@ -4522,6 +4424,7 @@ Quals & Field & Type & Description \\
 $\mathit{RW}$ &  {\tt name/description} & string & a notes field containg 
human-readable description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt software\_version} & (string $\rightarrow$ 
string) Map & version strings \\
 $\mathit{RW}$ &  {\tt other\_config} & (string $\rightarrow$ string) Map & 
additional configuration \\
+$\mathit{RO}_\mathit{run}$ &  {\tt supported\_bootloaders} & string Set & a 
list of the bootloaders installed on the machine \\
 $\mathit{RO}_\mathit{run}$ &  {\tt resident\_VMs} & (VM ref) Set & list of VMs 
currently resident on host \\
 $\mathit{RW}$ &  {\tt logging} & (string $\rightarrow$ string) Map & logging 
configuration \\
 $\mathit{RO}_\mathit{run}$ &  {\tt PIFs} & (PIF ref) Set & physical network 
interfaces \\
@@ -5050,6 +4953,38 @@ void
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
+\subsubsection{RPC name:~get\_supported\_bootloaders}
+
+{\bf Overview:} 
+Get the supported\_bootloaders field of the given host.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (string Set) get_supported_bootloaders (session_id s, host 
ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt host ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+string Set
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
 \subsubsection{RPC name:~get\_resident\_VMs}
 
 {\bf Overview:} 
@@ -5476,70 +5411,6 @@ host\_metrics ref
 
 
 value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~create}
-
-{\bf Overview:} 
-Create a new host instance, and return its handle.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} (host ref) create (session_id s, host record 
args)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt host record } & args & All constructor arguments \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-host ref
-}
-
-
-reference to the newly created object
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~destroy}
-
-{\bf Overview:} 
-Destroy the specified host instance.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void destroy (session_id s, host ref self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt host ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-void
-}
-
-
-
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
@@ -6808,28 +6679,707 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{ins}$ &  {\tt VM} & VM ref & virtual machine to which 
this vif is connected \\
 $\mathit{RW}$ &  {\tt MAC} & string & ethernet MAC address of virtual 
interface, as exposed to guest \\
 $\mathit{RW}$ &  {\tt MTU} & int & MTU in octets \\
+$\mathit{RW}$ &  {\tt qos/algorithm\_type} & string & QoS algorithm to use \\
+$\mathit{RW}$ &  {\tt qos/algorithm\_params} & (string $\rightarrow$ string) 
Map & Paramters for chosen QoS algorithm \\
+$\mathit{RO}_\mathit{run}$ &  {\tt metrics} & VIF\_metrics ref & metrics 
associated with this VIF. \\
+\hline
+\end{longtable}
+\subsection{Additional RPCs associated with class: VIF}
+\subsubsection{RPC name:~get\_uuid}
+
+{\bf Overview:} 
+Get the uuid field of the given VIF.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} string get_uuid (session_id s, VIF ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+string
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_device}
+
+{\bf Overview:} 
+Get the device field of the given VIF.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} string get_device (session_id s, VIF ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+string
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~set\_device}
+
+{\bf Overview:} 
+Set the device field of the given VIF.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void set_device (session_id s, VIF ref self, string 
value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & reference to the object \\ \hline 
+
+{\tt string } & value & New value to set \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_network}
+
+{\bf Overview:} 
+Get the network field of the given VIF.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (network ref) get_network (session_id s, VIF ref 
self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+network ref
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_VM}
+
+{\bf Overview:} 
+Get the VM field of the given VIF.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (VM ref) get_VM (session_id s, VIF ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+VM ref
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_MAC}
+
+{\bf Overview:} 
+Get the MAC field of the given VIF.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} string get_MAC (session_id s, VIF ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+string
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~set\_MAC}
+
+{\bf Overview:} 
+Set the MAC field of the given VIF.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void set_MAC (session_id s, VIF ref self, string 
value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & reference to the object \\ \hline 
+
+{\tt string } & value & New value to set \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_MTU}
+
+{\bf Overview:} 
+Get the MTU field of the given VIF.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} int get_MTU (session_id s, VIF ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+int
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~set\_MTU}
+
+{\bf Overview:} 
+Set the MTU field of the given VIF.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void set_MTU (session_id s, VIF ref self, int 
value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & reference to the object \\ \hline 
+
+{\tt int } & value & New value to set \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_qos\_algorithm\_type}
+
+{\bf Overview:} 
+Get the qos/algorithm\_type field of the given VIF.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} string get_qos_algorithm_type (session_id s, VIF ref 
self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+string
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~set\_qos\_algorithm\_type}
+
+{\bf Overview:} 
+Set the qos/algorithm\_type field of the given VIF.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void set_qos_algorithm_type (session_id s, VIF ref self, 
string value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & reference to the object \\ \hline 
+
+{\tt string } & value & New value to set \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_qos\_algorithm\_params}
+
+{\bf Overview:} 
+Get the qos/algorithm\_params field of the given VIF.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} ((string -> string) Map) get_qos_algorithm_params (session_id 
s, VIF ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+(string $\rightarrow$ string) Map
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~set\_qos\_algorithm\_params}
+
+{\bf Overview:} 
+Set the qos/algorithm\_params field of the given VIF.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void set_qos_algorithm_params (session_id s, VIF ref self, 
(string -> string) Map value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & reference to the object \\ \hline 
+
+{\tt (string $\rightarrow$ string) Map } & value & New value to set \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~add\_to\_qos\_algorithm\_params}
+
+{\bf Overview:} 
+Add the given key-value pair to the qos/algorithm\_params field of the
+given VIF.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void add_to_qos_algorithm_params (session_id s, VIF ref self, 
string key, string value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & reference to the object \\ \hline 
+
+{\tt string } & key & Key to add \\ \hline 
+
+{\tt string } & value & Value to add \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~remove\_from\_qos\_algorithm\_params}
+
+{\bf Overview:} 
+Remove the given key and its corresponding value from the
+qos/algorithm\_params field of the given VIF.  If the key is not in that
+Map, then do nothing.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void remove_from_qos_algorithm_params (session_id s, VIF ref 
self, string key)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & reference to the object \\ \hline 
+
+{\tt string } & key & Key to remove \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_metrics}
+
+{\bf Overview:} 
+Get the metrics field of the given VIF.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (VIF_metrics ref) get_metrics (session_id s, VIF ref 
self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+VIF\_metrics ref
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~create}
+
+{\bf Overview:} 
+Create a new VIF instance, and return its handle.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (VIF ref) create (session_id s, VIF record args)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF record } & args & All constructor arguments \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+VIF ref
+}
+
+
+reference to the newly created object
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~destroy}
+
+{\bf Overview:} 
+Destroy the specified VIF instance.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void destroy (session_id s, VIF ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_by\_uuid}
+
+{\bf Overview:} 
+Get a reference to the VIF instance with the specified UUID.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (VIF ref) get_by_uuid (session_id s, string 
uuid)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt string } & uuid & UUID of object to return \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+VIF ref
+}
+
+
+reference to the object
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_record}
+
+{\bf Overview:} 
+Get a record containing the current state of the given VIF.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (VIF record) get_record (session_id s, VIF ref 
self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+VIF record
+}
+
+
+all fields from the object
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+
+\vspace{1cm}
+\newpage
+\section{Class: VIF\_metrics}
+\subsection{Fields for class: VIF\_metrics}
+\begin{longtable}{|lllp{0.38\textwidth}|}
+\hline
+\multicolumn{1}{|l}{Name} & \multicolumn{3}{l|}{\bf VIF\_metrics} \\
+\multicolumn{1}{|l}{Description} & \multicolumn{3}{l|}{\parbox{11cm}{\em
+The metrics associated with a virtual network device.}} \\
+\hline
+Quals & Field & Type & Description \\
+\hline
+$\mathit{RO}_\mathit{run}$ &  {\tt uuid} & string & unique identifier/object 
reference \\
 $\mathit{RO}_\mathit{run}$ &  {\tt io/read\_kbs} & float & Read bandwidth 
(KiB/s) \\
 $\mathit{RO}_\mathit{run}$ &  {\tt io/write\_kbs} & float & Write bandwidth 
(KiB/s) \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: VIF}
+\subsection{Additional RPCs associated with class: VIF\_metrics}
 \subsubsection{RPC name:~get\_uuid}
 
 {\bf Overview:} 
-Get the uuid field of the given VIF.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} string get_uuid (session_id s, VIF ref self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VIF ref } & self & reference to the object \\ \hline 
+Get the uuid field of the given VIF\_metrics.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} string get_uuid (session_id s, VIF_metrics ref 
self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF\_metrics ref } & self & reference to the object \\ \hline 
 
 \end{tabular}
 
@@ -6845,285 +7395,23 @@ value of the field
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
-\subsubsection{RPC name:~get\_device}
-
-{\bf Overview:} 
-Get the device field of the given VIF.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} string get_device (session_id s, VIF ref self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VIF ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-string
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~set\_device}
-
-{\bf Overview:} 
-Set the device field of the given VIF.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void set_device (session_id s, VIF ref self, string 
value)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VIF ref } & self & reference to the object \\ \hline 
-
-{\tt string } & value & New value to set \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-void
-}
-
-
-
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_network}
-
-{\bf Overview:} 
-Get the network field of the given VIF.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} (network ref) get_network (session_id s, VIF ref 
self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VIF ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-network ref
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_VM}
-
-{\bf Overview:} 
-Get the VM field of the given VIF.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} (VM ref) get_VM (session_id s, VIF ref self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VIF ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-VM ref
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_MAC}
-
-{\bf Overview:} 
-Get the MAC field of the given VIF.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} string get_MAC (session_id s, VIF ref self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VIF ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-string
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~set\_MAC}
-
-{\bf Overview:} 
-Set the MAC field of the given VIF.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void set_MAC (session_id s, VIF ref self, string 
value)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VIF ref } & self & reference to the object \\ \hline 
-
-{\tt string } & value & New value to set \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-void
-}
-
-
-
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_MTU}
-
-{\bf Overview:} 
-Get the MTU field of the given VIF.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} int get_MTU (session_id s, VIF ref self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VIF ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-int
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~set\_MTU}
-
-{\bf Overview:} 
-Set the MTU field of the given VIF.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void set_MTU (session_id s, VIF ref self, int 
value)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VIF ref } & self & reference to the object \\ \hline 
-
-{\tt int } & value & New value to set \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-void
-}
-
-
-
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
 \subsubsection{RPC name:~get\_io\_read\_kbs}
 
 {\bf Overview:} 
-Get the io/read\_kbs field of the given VIF.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} float get_io_read_kbs (session_id s, VIF ref 
self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VIF ref } & self & reference to the object \\ \hline 
+Get the io/read\_kbs field of the given VIF\_metrics.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} float get_io_read_kbs (session_id s, VIF_metrics ref 
self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF\_metrics ref } & self & reference to the object \\ \hline 
 
 \end{tabular}
 
@@ -7142,20 +7430,20 @@ value of the field
 \subsubsection{RPC name:~get\_io\_write\_kbs}
 
 {\bf Overview:} 
-Get the io/write\_kbs field of the given VIF.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} float get_io_write_kbs (session_id s, VIF ref 
self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VIF ref } & self & reference to the object \\ \hline 
+Get the io/write\_kbs field of the given VIF\_metrics.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} float get_io_write_kbs (session_id s, VIF_metrics ref 
self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF\_metrics ref } & self & reference to the object \\ \hline 
 
 \end{tabular}
 
@@ -7171,77 +7459,13 @@ value of the field
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
-\subsubsection{RPC name:~create}
-
-{\bf Overview:} 
-Create a new VIF instance, and return its handle.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} (VIF ref) create (session_id s, VIF record args)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VIF record } & args & All constructor arguments \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-VIF ref
-}
-
-
-reference to the newly created object
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~destroy}
-
-{\bf Overview:} 
-Destroy the specified VIF instance.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void destroy (session_id s, VIF ref self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VIF ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-void
-}
-
-
-
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
 \subsubsection{RPC name:~get\_by\_uuid}
 
 {\bf Overview:} 
-Get a reference to the VIF instance with the specified UUID.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} (VIF ref) get_by_uuid (session_id s, string 
uuid)\end{verbatim}
+Get a reference to the VIF\_metrics instance with the specified UUID.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (VIF_metrics ref) get_by_uuid (session_id s, string 
uuid)\end{verbatim}
 
 
 \noindent{\bf Arguments:}
@@ -7259,7 +7483,7 @@ Get a reference to the VIF instance with
 
  \noindent {\bf Return Type:} 
 {\tt 
-VIF ref
+VIF\_metrics ref
 }
 
 
@@ -7270,28 +7494,28 @@ reference to the object
 \subsubsection{RPC name:~get\_record}
 
 {\bf Overview:} 
-Get a record containing the current state of the given VIF.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} (VIF record) get_record (session_id s, VIF ref 
self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VIF ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-VIF record
+Get a record containing the current state of the given VIF\_metrics.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (VIF_metrics record) get_record (session_id s, VIF_metrics 
ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF\_metrics ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+VIF\_metrics record
 }
 
 
@@ -9562,63 +9786,808 @@ Quals & Field & Type & Description \\
 $\mathit{RW}$ &  {\tt bootable} & bool & true if this VBD is bootable \\
 $\mathit{RW}$ &  {\tt mode} & vbd\_mode & the mode the VBD should be mounted 
with \\
 $\mathit{RW}$ &  {\tt type} & vbd\_type & how the VBD will appear to the guest 
(e.g. disk or CD) \\
+$\mathit{RW}$ &  {\tt qos/algorithm\_type} & string & QoS algorithm to use \\
+$\mathit{RW}$ &  {\tt qos/algorithm\_params} & (string $\rightarrow$ string) 
Map & Paramters for chosen QoS algorithm \\
+$\mathit{RO}_\mathit{run}$ &  {\tt metrics} & VBD\_metrics ref & metrics 
associated with this VBD. \\
+\hline
+\end{longtable}
+\subsection{Additional RPCs associated with class: VBD}
+\subsubsection{RPC name:~media\_change}
+
+{\bf Overview:} 
+Change the media in the device for CDROM-like devices only. For other
+devices, detach the VBD and attach a new one.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void media_change (session_id s, VBD ref vbd, VDI ref 
vdi)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & vbd & The vbd representing the CDROM-like device \\ \hline 
+
+{\tt VDI ref } & vdi & The new VDI to 'insert' \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_uuid}
+
+{\bf Overview:} 
+Get the uuid field of the given VBD.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} string get_uuid (session_id s, VBD ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+string
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_VM}
+
+{\bf Overview:} 
+Get the VM field of the given VBD.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (VM ref) get_VM (session_id s, VBD ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+VM ref
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_VDI}
+
+{\bf Overview:} 
+Get the VDI field of the given VBD.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (VDI ref) get_VDI (session_id s, VBD ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+VDI ref
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_device}
+
+{\bf Overview:} 
+Get the device field of the given VBD.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} string get_device (session_id s, VBD ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+string
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~set\_device}
+
+{\bf Overview:} 
+Set the device field of the given VBD.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void set_device (session_id s, VBD ref self, string 
value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+{\tt string } & value & New value to set \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_bootable}
+
+{\bf Overview:} 
+Get the bootable field of the given VBD.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} bool get_bootable (session_id s, VBD ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+bool
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~set\_bootable}
+
+{\bf Overview:} 
+Set the bootable field of the given VBD.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void set_bootable (session_id s, VBD ref self, bool 
value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+{\tt bool } & value & New value to set \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_mode}
+
+{\bf Overview:} 
+Get the mode field of the given VBD.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (vbd_mode) get_mode (session_id s, VBD ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+vbd\_mode
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~set\_mode}
+
+{\bf Overview:} 
+Set the mode field of the given VBD.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void set_mode (session_id s, VBD ref self, vbd_mode 
value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+{\tt vbd\_mode } & value & New value to set \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_type}
+
+{\bf Overview:} 
+Get the type field of the given VBD.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (vbd_type) get_type (session_id s, VBD ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+vbd\_type
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~set\_type}
+
+{\bf Overview:} 
+Set the type field of the given VBD.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void set_type (session_id s, VBD ref self, vbd_type 
value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+{\tt vbd\_type } & value & New value to set \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_qos\_algorithm\_type}
+
+{\bf Overview:} 
+Get the qos/algorithm\_type field of the given VBD.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} string get_qos_algorithm_type (session_id s, VBD ref 
self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+string
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~set\_qos\_algorithm\_type}
+
+{\bf Overview:} 
+Set the qos/algorithm\_type field of the given VBD.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void set_qos_algorithm_type (session_id s, VBD ref self, 
string value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+{\tt string } & value & New value to set \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_qos\_algorithm\_params}
+
+{\bf Overview:} 
+Get the qos/algorithm\_params field of the given VBD.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} ((string -> string) Map) get_qos_algorithm_params (session_id 
s, VBD ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+(string $\rightarrow$ string) Map
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~set\_qos\_algorithm\_params}
+
+{\bf Overview:} 
+Set the qos/algorithm\_params field of the given VBD.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void set_qos_algorithm_params (session_id s, VBD ref self, 
(string -> string) Map value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+{\tt (string $\rightarrow$ string) Map } & value & New value to set \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~add\_to\_qos\_algorithm\_params}
+
+{\bf Overview:} 
+Add the given key-value pair to the qos/algorithm\_params field of the
+given VBD.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void add_to_qos_algorithm_params (session_id s, VBD ref self, 
string key, string value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+{\tt string } & key & Key to add \\ \hline 
+
+{\tt string } & value & Value to add \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~remove\_from\_qos\_algorithm\_params}
+
+{\bf Overview:} 
+Remove the given key and its corresponding value from the
+qos/algorithm\_params field of the given VBD.  If the key is not in that
+Map, then do nothing.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void remove_from_qos_algorithm_params (session_id s, VBD ref 
self, string key)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+{\tt string } & key & Key to remove \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_metrics}
+
+{\bf Overview:} 
+Get the metrics field of the given VBD.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (VBD_metrics ref) get_metrics (session_id s, VBD ref 
self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+VBD\_metrics ref
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~create}
+
+{\bf Overview:} 
+Create a new VBD instance, and return its handle.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (VBD ref) create (session_id s, VBD record args)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD record } & args & All constructor arguments \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+VBD ref
+}
+
+
+reference to the newly created object
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~destroy}
+
+{\bf Overview:} 
+Destroy the specified VBD instance.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void destroy (session_id s, VBD ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_by\_uuid}
+
+{\bf Overview:} 
+Get a reference to the VBD instance with the specified UUID.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (VBD ref) get_by_uuid (session_id s, string 
uuid)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt string } & uuid & UUID of object to return \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+VBD ref
+}
+
+
+reference to the object
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_record}
+
+{\bf Overview:} 
+Get a record containing the current state of the given VBD.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (VBD record) get_record (session_id s, VBD ref 
self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+VBD record
+}
+
+
+all fields from the object
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+
+\vspace{1cm}
+\newpage
+\section{Class: VBD\_metrics}
+\subsection{Fields for class: VBD\_metrics}
+\begin{longtable}{|lllp{0.38\textwidth}|}
+\hline
+\multicolumn{1}{|l}{Name} & \multicolumn{3}{l|}{\bf VBD\_metrics} \\
+\multicolumn{1}{|l}{Description} & \multicolumn{3}{l|}{\parbox{11cm}{\em
+The metrics associated with a virtual block device.}} \\
+\hline
+Quals & Field & Type & Description \\
+\hline
+$\mathit{RO}_\mathit{run}$ &  {\tt uuid} & string & unique identifier/object 
reference \\
 $\mathit{RO}_\mathit{run}$ &  {\tt io/read\_kbs} & float & Read bandwidth 
(KiB/s) \\
 $\mathit{RO}_\mathit{run}$ &  {\tt io/write\_kbs} & float & Write bandwidth 
(KiB/s) \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: VBD}
-\subsubsection{RPC name:~media\_change}
-
-{\bf Overview:} 
-Change the media in the device for CDROM-like devices only. For other
-devices, detach the VBD and attach a new one.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void media_change (session_id s, VBD ref vbd, VDI ref 
vdi)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VBD ref } & vbd & The vbd representing the CDROM-like device \\ \hline 
-
-{\tt VDI ref } & vdi & The new VDI to 'insert' \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-void
-}
-
-
-
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
+\subsection{Additional RPCs associated with class: VBD\_metrics}
 \subsubsection{RPC name:~get\_uuid}
 
 {\bf Overview:} 
-Get the uuid field of the given VBD.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} string get_uuid (session_id s, VBD ref self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VBD ref } & self & reference to the object \\ \hline 
+Get the uuid field of the given VBD\_metrics.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} string get_uuid (session_id s, VBD_metrics ref 
self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD\_metrics ref } & self & reference to the object \\ \hline 
 
 \end{tabular}
 
@@ -9634,351 +10603,23 @@ value of the field
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
-\subsubsection{RPC name:~get\_VM}
-
-{\bf Overview:} 
-Get the VM field of the given VBD.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} (VM ref) get_VM (session_id s, VBD ref self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VBD ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-VM ref
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_VDI}
-
-{\bf Overview:} 
-Get the VDI field of the given VBD.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} (VDI ref) get_VDI (session_id s, VBD ref self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VBD ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-VDI ref
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_device}
-
-{\bf Overview:} 
-Get the device field of the given VBD.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} string get_device (session_id s, VBD ref self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VBD ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-string
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~set\_device}
-
-{\bf Overview:} 
-Set the device field of the given VBD.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void set_device (session_id s, VBD ref self, string 
value)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VBD ref } & self & reference to the object \\ \hline 
-
-{\tt string } & value & New value to set \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-void
-}
-
-
-
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_bootable}
-
-{\bf Overview:} 
-Get the bootable field of the given VBD.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} bool get_bootable (session_id s, VBD ref self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VBD ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-bool
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~set\_bootable}
-
-{\bf Overview:} 
-Set the bootable field of the given VBD.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void set_bootable (session_id s, VBD ref self, bool 
value)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VBD ref } & self & reference to the object \\ \hline 
-
-{\tt bool } & value & New value to set \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-void
-}
-
-
-
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_mode}
-
-{\bf Overview:} 
-Get the mode field of the given VBD.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} (vbd_mode) get_mode (session_id s, VBD ref self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VBD ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-vbd\_mode
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~set\_mode}
-
-{\bf Overview:} 
-Set the mode field of the given VBD.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void set_mode (session_id s, VBD ref self, vbd_mode 
value)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VBD ref } & self & reference to the object \\ \hline 
-
-{\tt vbd\_mode } & value & New value to set \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-void
-}
-
-
-
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_type}
-
-{\bf Overview:} 
-Get the type field of the given VBD.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} (vbd_type) get_type (session_id s, VBD ref self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VBD ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-vbd\_type
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~set\_type}
-
-{\bf Overview:} 
-Set the type field of the given VBD.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void set_type (session_id s, VBD ref self, vbd_type 
value)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VBD ref } & self & reference to the object \\ \hline 
-
-{\tt vbd\_type } & value & New value to set \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-void
-}
-
-
-
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
 \subsubsection{RPC name:~get\_io\_read\_kbs}
 
 {\bf Overview:} 
-Get the io/read\_kbs field of the given VBD.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} float get_io_read_kbs (session_id s, VBD ref 
self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VBD ref } & self & reference to the object \\ \hline 
+Get the io/read\_kbs field of the given VBD\_metrics.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} float get_io_read_kbs (session_id s, VBD_metrics ref 
self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD\_metrics ref } & self & reference to the object \\ \hline 
 
 \end{tabular}
 
@@ -9997,20 +10638,20 @@ value of the field
 \subsubsection{RPC name:~get\_io\_write\_kbs}
 
 {\bf Overview:} 
-Get the io/write\_kbs field of the given VBD.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} float get_io_write_kbs (session_id s, VBD ref 
self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VBD ref } & self & reference to the object \\ \hline 
+Get the io/write\_kbs field of the given VBD\_metrics.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} float get_io_write_kbs (session_id s, VBD_metrics ref 
self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD\_metrics ref } & self & reference to the object \\ \hline 
 
 \end{tabular}
 
@@ -10026,77 +10667,13 @@ value of the field
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
-\subsubsection{RPC name:~create}
-
-{\bf Overview:} 
-Create a new VBD instance, and return its handle.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} (VBD ref) create (session_id s, VBD record args)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VBD record } & args & All constructor arguments \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-VBD ref
-}
-
-
-reference to the newly created object
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~destroy}
-
-{\bf Overview:} 
-Destroy the specified VBD instance.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void destroy (session_id s, VBD ref self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VBD ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-void
-}
-
-
-
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
 \subsubsection{RPC name:~get\_by\_uuid}
 
 {\bf Overview:} 
-Get a reference to the VBD instance with the specified UUID.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} (VBD ref) get_by_uuid (session_id s, string 
uuid)\end{verbatim}
+Get a reference to the VBD\_metrics instance with the specified UUID.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (VBD_metrics ref) get_by_uuid (session_id s, string 
uuid)\end{verbatim}
 
 
 \noindent{\bf Arguments:}
@@ -10114,7 +10691,7 @@ Get a reference to the VBD instance with
 
  \noindent {\bf Return Type:} 
 {\tt 
-VBD ref
+VBD\_metrics ref
 }
 
 
@@ -10125,28 +10702,28 @@ reference to the object
 \subsubsection{RPC name:~get\_record}
 
 {\bf Overview:} 
-Get a record containing the current state of the given VBD.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} (VBD record) get_record (session_id s, VBD ref 
self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VBD ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-VBD record
+Get a record containing the current state of the given VBD\_metrics.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (VBD_metrics record) get_record (session_id s, VBD_metrics 
ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD\_metrics ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+VBD\_metrics record
 }
 
 
@@ -10985,8 +11562,9 @@ Quals & Field & Type & Description \\
 \hline
 $\mathit{RO}_\mathit{run}$ &  {\tt uuid} & string & unique identifier/object 
reference \\
 $\mathit{RO}_\mathit{run}$ &  {\tt protocol} & console\_protocol & the 
protocol used by this console \\
-$\mathit{RO}_\mathit{run}$ &  {\tt uri} & string & URI for the console service 
\\
+$\mathit{RO}_\mathit{run}$ &  {\tt location} & string & URI for the console 
service \\
 $\mathit{RO}_\mathit{run}$ &  {\tt VM} & VM ref & VM to which this console is 
attached \\
+$\mathit{RW}$ &  {\tt other\_config} & (string $\rightarrow$ string) Map & 
additional configuration \\
 \hline
 \end{longtable}
 \subsection{Additional RPCs associated with class: console}
@@ -11054,13 +11632,13 @@ value of the field
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
-\subsubsection{RPC name:~get\_uri}
-
-{\bf Overview:} 
-Get the uri field of the given console.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} string get_uri (session_id s, console ref self)\end{verbatim}
+\subsubsection{RPC name:~get\_location}
+
+{\bf Overview:} 
+Get the location field of the given console.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} string get_location (session_id s, console ref 
self)\end{verbatim}
 
 
 \noindent{\bf Arguments:}
@@ -11115,6 +11693,145 @@ VM ref
 
 
 value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_other\_config}
+
+{\bf Overview:} 
+Get the other\_config field of the given console.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} ((string -> string) Map) get_other_config (session_id s, 
console ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt console ref } & self & reference to the object \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+(string $\rightarrow$ string) Map
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~set\_other\_config}
+
+{\bf Overview:} 
+Set the other\_config field of the given console.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void set_other_config (session_id s, console ref self, 
(string -> string) Map value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt console ref } & self & reference to the object \\ \hline 
+
+{\tt (string $\rightarrow$ string) Map } & value & New value to set \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~add\_to\_other\_config}
+
+{\bf Overview:} 
+Add the given key-value pair to the other\_config field of the given
+console.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void add_to_other_config (session_id s, console ref self, 
string key, string value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt console ref } & self & reference to the object \\ \hline 
+
+{\tt string } & key & Key to add \\ \hline 
+
+{\tt string } & value & Value to add \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~remove\_from\_other\_config}
+
+{\bf Overview:} 
+Remove the given key and its corresponding value from the other\_config
+field of the given console.  If the key is not in that Map, then do
+nothing.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void remove_from_other_config (session_id s, console ref 
self, string key)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt console ref } & self & reference to the object \\ \hline 
+
+{\tt string } & key & Key to remove \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
@@ -11767,34 +12484,15 @@ Each possible error code is documented i
 
 \subsection{Error Codes}
 
-\subsubsection{HOST\_CPU\_HANDLE\_INVALID}
-
-You gave an invalid host\_cpu handle.  The host\_cpu may have recently been
-deleted.  The handle parameter echoes the bad value given.
+\subsubsection{HANDLE\_INVALID}
+
+You gave an invalid handle.  The object may have recently been deleted. 
+The class parameter gives the type of reference given, and the handle
+parameter echoes the bad value given.
 
 \vspace{0.3cm}
 {\bf Signature:}
-\begin{verbatim}HOST_CPU_HANDLE_INVALID(handle)\end{verbatim}
-\begin{center}\rule{10em}{0.1pt}\end{center}
-
-\subsubsection{HOST\_HANDLE\_INVALID}
-
-You gave an invalid host handle.  The host may have recently been deleted. 
-The handle parameter echoes the bad value given.
-
-\vspace{0.3cm}
-{\bf Signature:}
-\begin{verbatim}HOST_HANDLE_INVALID(handle)\end{verbatim}
-\begin{center}\rule{10em}{0.1pt}\end{center}
-
-\subsubsection{HOST\_METRICS\_HANDLE\_INVALID}
-
-You gave an invalid host\_metrics handle.  The host\_metrics may have
-recently been deleted.  The handle parameter echoes the bad value given.
-
-\vspace{0.3cm}
-{\bf Signature:}
-\begin{verbatim}HOST_METRICS_HANDLE_INVALID(handle)\end{verbatim}
+\begin{verbatim}HANDLE_INVALID(class, handle)\end{verbatim}
 \begin{center}\rule{10em}{0.1pt}\end{center}
 
 \subsubsection{INTERNAL\_ERROR}
@@ -11854,18 +12552,7 @@ You attempted an operation that was not 
 You attempted an operation that was not allowed.
 
 \vspace{0.3cm}
-{\bf Signature:}
-\begin{verbatim}OPERATION_NOT_ALLOWED()\end{verbatim}
-\begin{center}\rule{10em}{0.1pt}\end{center}
-
-\subsubsection{PIF\_HANDLE\_INVALID}
-
-You gave an invalid PIF handle.  The PIF may have recently been deleted. 
-The handle parameter echoes the bad value given.
-
-\vspace{0.3cm}
-{\bf Signature:}
-\begin{verbatim}PIF_HANDLE_INVALID(handle)\end{verbatim}
+No parameters.
 \begin{center}\rule{10em}{0.1pt}\end{center}
 
 \subsubsection{PIF\_IS\_PHYSICAL}
@@ -11877,16 +12564,6 @@ PIF handle you gave.
 \vspace{0.3cm}
 {\bf Signature:}
 \begin{verbatim}PIF_IS_PHYSICAL(PIF)\end{verbatim}
-\begin{center}\rule{10em}{0.1pt}\end{center}
-
-\subsubsection{PIF\_METRICS\_HANDLE\_INVALID}
-
-You gave an invalid PIF\_metrics handle.  The PIF\_metrics may have
-recently been deleted.  The handle parameter echoes the bad value given.
-
-\vspace{0.3cm}
-{\bf Signature:}
-\begin{verbatim}PIF_METRICS_HANDLE_INVALID(handle)\end{verbatim}
 \begin{center}\rule{10em}{0.1pt}\end{center}
 
 \subsubsection{SESSION\_AUTHENTICATION\_FAILED}
@@ -11910,26 +12587,6 @@ current connection.  The handle paramete
 \begin{verbatim}SESSION_INVALID(handle)\end{verbatim}
 \begin{center}\rule{10em}{0.1pt}\end{center}
 
-\subsubsection{SR\_HANDLE\_INVALID}
-
-You gave an invalid SR handle.  The SR may have recently been deleted.  The
-handle parameter echoes the bad value given.
-
-\vspace{0.3cm}
-{\bf Signature:}
-\begin{verbatim}SR_HANDLE_INVALID(handle)\end{verbatim}
-\begin{center}\rule{10em}{0.1pt}\end{center}
-
-\subsubsection{TASK\_HANDLE\_INVALID}
-
-You gave an invalid task handle.  The task may have recently been deleted. 
-The handle parameter echoes the bad value given.
-
-\vspace{0.3cm}
-{\bf Signature:}
-\begin{verbatim}TASK_HANDLE_INVALID(handle)\end{verbatim}
-\begin{center}\rule{10em}{0.1pt}\end{center}
-
 \subsubsection{VALUE\_NOT\_SUPPORTED}
 
 You attempted to set a value that is not supported by this implementation. 
@@ -11939,36 +12596,6 @@ returned.  Also returned is a developer-
 \vspace{0.3cm}
 {\bf Signature:}
 \begin{verbatim}VALUE_NOT_SUPPORTED(field, value, reason)\end{verbatim}
-\begin{center}\rule{10em}{0.1pt}\end{center}
-
-\subsubsection{VBD\_HANDLE\_INVALID}
-
-You gave an invalid VBD handle.  The VBD may have recently been deleted. 
-The handle parameter echoes the bad value given.
-
-\vspace{0.3cm}
-{\bf Signature:}
-\begin{verbatim}VBD_HANDLE_INVALID(handle)\end{verbatim}
-\begin{center}\rule{10em}{0.1pt}\end{center}
-
-\subsubsection{VDI\_HANDLE\_INVALID}
-
-You gave an invalid VDI handle.  The VDI may have recently been deleted. 
-The handle parameter echoes the bad value given.
-
-\vspace{0.3cm}
-{\bf Signature:}
-\begin{verbatim}VDI_HANDLE_INVALID(handle)\end{verbatim}
-\begin{center}\rule{10em}{0.1pt}\end{center}
-
-\subsubsection{VIF\_HANDLE\_INVALID}
-
-You gave an invalid VIF handle.  The VIF may have recently been deleted. 
-The handle parameter echoes the bad value given.
-
-\vspace{0.3cm}
-{\bf Signature:}
-\begin{verbatim}VIF_HANDLE_INVALID(handle)\end{verbatim}
 \begin{center}\rule{10em}{0.1pt}\end{center}
 
 \subsubsection{VLAN\_TAG\_INVALID}
@@ -11991,36 +12618,6 @@ expected and actual VM state at the time
 \vspace{0.3cm}
 {\bf Signature:}
 \begin{verbatim}VM_BAD_POWER_STATE(vm, expected, actual)\end{verbatim}
-\begin{center}\rule{10em}{0.1pt}\end{center}
-
-\subsubsection{VM\_HANDLE\_INVALID}
-
-You gave an invalid VM handle.  The VM may have recently been deleted.  The
-handle parameter echoes the bad value given.
-
-\vspace{0.3cm}
-{\bf Signature:}
-\begin{verbatim}VM_HANDLE_INVALID(handle)\end{verbatim}
-\begin{center}\rule{10em}{0.1pt}\end{center}
-
-\subsubsection{VM\_METRICS\_HANDLE\_INVALID}
-
-You gave an invalid VM\_metrics handle.  The VM\_metrics may have recently
-been deleted.  The handle parameter echoes the bad value given.
-
-\vspace{0.3cm}
-{\bf Signature:}
-\begin{verbatim}VM_METRICS_HANDLE_INVALID(handle)\end{verbatim}
-\begin{center}\rule{10em}{0.1pt}\end{center}
-
-\subsubsection{VTPM\_HANDLE\_INVALID}
-
-You gave an invalid VTPM handle.  The VTPM may have recently been deleted. 
-The handle parameter echoes the bad value given.
-
-\vspace{0.3cm}
-{\bf Signature:}
-\begin{verbatim}VTPM_HANDLE_INVALID(handle)\end{verbatim}
 \begin{center}\rule{10em}{0.1pt}\end{center}
 
 
diff -r 9364bea18bc4 -r 202eb735b425 
linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c        Thu Feb 22 
09:42:13 2007 -0700
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c        Thu Feb 22 
10:15:29 2007 -0700
@@ -490,6 +490,11 @@ static void dispatch_rw_block_io(blkif_t
 
        for (i = 0; i < nbio; i++)
                submit_bio(operation, biolist[i]);
+
+       if (operation == READ)
+               blkif->st_rd_sect += preq.nr_sects;
+       else if (operation == WRITE)
+               blkif->st_wr_sect += preq.nr_sects;
 
        return;
 
diff -r 9364bea18bc4 -r 202eb735b425 
linux-2.6-xen-sparse/drivers/xen/blkback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Thu Feb 22 09:42:13 
2007 -0700
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Thu Feb 22 10:15:29 
2007 -0700
@@ -88,6 +88,8 @@ typedef struct blkif_st {
        int                 st_wr_req;
        int                 st_oo_req;
        int                 st_br_req;
+       int                 st_rd_sect;
+       int                 st_wr_sect;
 
        wait_queue_head_t waiting_to_free;
 
diff -r 9364bea18bc4 -r 202eb735b425 
linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Thu Feb 22 09:42:13 
2007 -0700
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Thu Feb 22 10:15:29 
2007 -0700
@@ -111,16 +111,20 @@ static void update_blkif_status(blkif_t 
        }                                                               \
        DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
 
-VBD_SHOW(oo_req, "%d\n", be->blkif->st_oo_req);
-VBD_SHOW(rd_req, "%d\n", be->blkif->st_rd_req);
-VBD_SHOW(wr_req, "%d\n", be->blkif->st_wr_req);
-VBD_SHOW(br_req, "%d\n", be->blkif->st_br_req);
+VBD_SHOW(oo_req,  "%d\n", be->blkif->st_oo_req);
+VBD_SHOW(rd_req,  "%d\n", be->blkif->st_rd_req);
+VBD_SHOW(wr_req,  "%d\n", be->blkif->st_wr_req);
+VBD_SHOW(br_req,  "%d\n", be->blkif->st_br_req);
+VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect);
+VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect);
 
 static struct attribute *vbdstat_attrs[] = {
        &dev_attr_oo_req.attr,
        &dev_attr_rd_req.attr,
        &dev_attr_wr_req.attr,
        &dev_attr_br_req.attr,
+       &dev_attr_rd_sect.attr,
+       &dev_attr_wr_sect.attr,
        NULL
 };
 
diff -r 9364bea18bc4 -r 202eb735b425 
linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c  Thu Feb 22 09:42:13 
2007 -0700
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c  Thu Feb 22 10:15:29 
2007 -0700
@@ -1195,7 +1195,7 @@ static void dispatch_rw_block_io(blkif_t
        int op, operation = (req->operation == BLKIF_OP_WRITE) ? WRITE : READ;
        struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
        unsigned int nseg;
-       int ret, i;
+       int ret, i, nr_sects = 0;
        tap_blkif_t *info;
        uint64_t sector;
        blkif_request_t *target;
@@ -1291,6 +1291,9 @@ static void dispatch_rw_block_io(blkif_t
                                          req->seg[i].gref, blkif->domid);
                        op++;
                }
+
+               nr_sects += (req->seg[i].last_sect - 
+                            req->seg[i].first_sect + 1);
        }
 
        ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, op);
@@ -1403,6 +1406,12 @@ static void dispatch_rw_block_io(blkif_t
        target->id = usr_idx;
        wmb(); /* blktap_poll() reads req_prod_pvt asynchronously */
        info->ufe_ring.req_prod_pvt++;
+
+       if (operation == READ)
+               blkif->st_rd_sect += nr_sects;
+       else if (operation == WRITE)
+               blkif->st_wr_sect += nr_sects;
+
        return;
 
  fail_flush:
diff -r 9364bea18bc4 -r 202eb735b425 
linux-2.6-xen-sparse/drivers/xen/blktap/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/common.h  Thu Feb 22 09:42:13 
2007 -0700
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/common.h  Thu Feb 22 10:15:29 
2007 -0700
@@ -76,6 +76,8 @@ typedef struct blkif_st {
        int                 st_rd_req;
        int                 st_wr_req;
        int                 st_oo_req;
+       int                 st_rd_sect;
+       int                 st_wr_sect;
 
        wait_queue_head_t waiting_to_free;
 
diff -r 9364bea18bc4 -r 202eb735b425 
linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c  Thu Feb 22 09:42:13 
2007 -0700
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c  Thu Feb 22 10:15:29 
2007 -0700
@@ -47,6 +47,7 @@ struct backend_info
        blkif_t *blkif;
        struct xenbus_watch backend_watch;
        int xenbus_id;
+       int group_added;
 };
 
 
@@ -112,6 +113,80 @@ static int blktap_name(blkif_t *blkif, c
        return 0;
 }
 
+/****************************************************************
+ *  sysfs interface for VBD I/O requests
+ */
+
+#define VBD_SHOW(name, format, args...)                                        
\
+       static ssize_t show_##name(struct device *_dev,                 \
+                                  struct device_attribute *attr,       \
+                                  char *buf)                           \
+       {                                                               \
+               struct xenbus_device *dev = to_xenbus_device(_dev);     \
+               struct backend_info *be = dev->dev.driver_data;         \
+                                                                       \
+               return sprintf(buf, format, ##args);                    \
+       }                                                               \
+       DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+
+VBD_SHOW(tap_oo_req,  "%d\n", be->blkif->st_oo_req);
+VBD_SHOW(tap_rd_req,  "%d\n", be->blkif->st_rd_req);
+VBD_SHOW(tap_wr_req,  "%d\n", be->blkif->st_wr_req);
+VBD_SHOW(tap_rd_sect, "%d\n", be->blkif->st_rd_sect);
+VBD_SHOW(tap_wr_sect, "%d\n", be->blkif->st_wr_sect);
+
+static struct attribute *tapstat_attrs[] = {
+       &dev_attr_tap_oo_req.attr,
+       &dev_attr_tap_rd_req.attr,
+       &dev_attr_tap_wr_req.attr,
+       &dev_attr_tap_rd_sect.attr,
+       &dev_attr_tap_wr_sect.attr,
+       NULL
+};
+
+static struct attribute_group tapstat_group = {
+       .name = "statistics",
+       .attrs = tapstat_attrs,
+};
+
+int xentap_sysfs_addif(struct xenbus_device *dev)
+{
+       int err;
+       struct backend_info *be = dev->dev.driver_data;
+       err = sysfs_create_group(&dev->dev.kobj, &tapstat_group);
+       if (!err)
+               be->group_added = 1;
+       return err;
+}
+
+void xentap_sysfs_delif(struct xenbus_device *dev)
+{
+       sysfs_remove_group(&dev->dev.kobj, &tapstat_group);
+}
+
+static int blktap_remove(struct xenbus_device *dev)
+{
+       struct backend_info *be = dev->dev.driver_data;
+
+       if (be->backend_watch.node) {
+               unregister_xenbus_watch(&be->backend_watch);
+               kfree(be->backend_watch.node);
+               be->backend_watch.node = NULL;
+       }
+       if (be->blkif) {
+               if (be->blkif->xenblkd)
+                       kthread_stop(be->blkif->xenblkd);
+               signal_tapdisk(be->blkif->dev_num);
+               tap_blkif_free(be->blkif);
+               be->blkif = NULL;
+       }
+       if (be->group_added)
+               xentap_sysfs_delif(be->dev);
+       kfree(be);
+       dev->dev.driver_data = NULL;
+       return 0;
+}
+
 static void tap_update_blkif_status(blkif_t *blkif)
 { 
        int err;
@@ -134,6 +209,13 @@ static void tap_update_blkif_status(blki
        err = blktap_name(blkif, name);
        if (err) {
                xenbus_dev_error(blkif->be->dev, err, "get blktap dev name");
+               return;
+       }
+
+       err = xentap_sysfs_addif(blkif->be->dev);
+       if (err) {
+               xenbus_dev_fatal(blkif->be->dev, err, 
+                                "creating sysfs entries");
                return;
        }
 
@@ -144,27 +226,6 @@ static void tap_update_blkif_status(blki
                xenbus_dev_fatal(blkif->be->dev, err, "start xenblkd");
                WPRINTK("Error starting thread\n");
        }
-}
-
-static int blktap_remove(struct xenbus_device *dev)
-{
-       struct backend_info *be = dev->dev.driver_data;
-
-       if (be->backend_watch.node) {
-               unregister_xenbus_watch(&be->backend_watch);
-               kfree(be->backend_watch.node);
-               be->backend_watch.node = NULL;
-       }
-       if (be->blkif) {
-               if (be->blkif->xenblkd)
-                       kthread_stop(be->blkif->xenblkd);
-               signal_tapdisk(be->blkif->dev_num);
-               tap_blkif_free(be->blkif);
-               be->blkif = NULL;
-       }
-       kfree(be);
-       dev->dev.driver_data = NULL;
-       return 0;
 }
 
 /**
diff -r 9364bea18bc4 -r 202eb735b425 tools/libfsimage/Makefile
--- a/tools/libfsimage/Makefile Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libfsimage/Makefile Thu Feb 22 10:15:29 2007 -0700
@@ -1,7 +1,7 @@ XEN_ROOT = ../..
 XEN_ROOT = ../..
 include $(XEN_ROOT)/tools/Rules.mk
 
-SUBDIRS-y = common ufs reiserfs
+SUBDIRS-y = common ufs reiserfs iso9660 fat
 SUBDIRS-y += $(shell ./check-libext2fs)
 
 .PHONY: all
diff -r 9364bea18bc4 -r 202eb735b425 tools/libfsimage/common/fsimage_grub.c
--- a/tools/libfsimage/common/fsimage_grub.c    Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libfsimage/common/fsimage_grub.c    Thu Feb 22 10:15:29 2007 -0700
@@ -122,6 +122,84 @@ fsig_disk_read_junk(void)
        return (&disk_read_junk);
 }
 
+#if defined(__i386__) || defined(__x86_64__)
+
+#ifdef __amd64
+#define BSF "bsfq"
+#else
+#define BSF "bsfl"
+#endif
+unsigned long
+fsig_log2 (unsigned long word)
+{
+  __asm__ (BSF " %1,%0"
+          : "=r" (word)
+          : "r" (word));
+  return word;
+}
+
+#elif defined(__ia64__)
+
+#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+# define ia64_popcnt(x) __builtin_popcountl(x)
+#else
+# define ia64_popcnt(x)                                     \
+  ({                                                        \
+    __u64 ia64_intri_res;                                   \
+    asm ("popcnt %0=%1" : "=r" (ia64_intri_res) : "r" (x)); \
+    ia64_intri_res;                                         \
+  })
+#endif
+
+unsigned long
+fsig_log2 (unsigned long word)
+{
+  unsigned long result;
+
+  result = ia64_popcnt((word - 1) & ~word);
+  return result;
+}
+
+#elif defined(__powerpc__)
+
+#ifdef __powerpc64__
+#define PPC_CNTLZL "cntlzd"
+#else
+#define PPC_CNTLZL "cntlzw"
+#endif
+#define BITS_PER_LONG (sizeof(long) * 8)
+
+static int
+__ilog2(unsigned long x)
+{
+  int lz;
+
+  asm (PPC_CNTLZL " %0,%1" : "=r" (lz) : "r" (x));
+  return BITS_PER_LONG - 1 - lz;
+}
+
+unsigned long
+fsig_log2 (unsigned long word)
+{
+  return __ilog2(word & -word);
+}
+
+#else /* Unoptimized */
+
+unsigned long
+fsig_log2 (unsigned long word)
+{
+  unsigned long result = 0;
+
+  while (!(word & 1UL))
+    {
+      result++;
+      word >>= 1;
+    }
+  return result;
+}
+#endif
+
 int
 fsig_devread(fsi_file_t *ffi, unsigned int sector, unsigned int offset,
     unsigned int bufsize, char *buf)
diff -r 9364bea18bc4 -r 202eb735b425 tools/libfsimage/common/fsimage_grub.h
--- a/tools/libfsimage/common/fsimage_grub.h    Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libfsimage/common/fsimage_grub.h    Thu Feb 22 10:15:29 2007 -0700
@@ -57,16 +57,19 @@ typedef struct fsig_plugin_ops {
 #define        disk_read_func (*fsig_disk_read_junk())
 #define        disk_read_hook (*fsig_disk_read_junk())
 #define        print_possibilities 0
+#define        noisy_printf
 
 #define        grub_memset memset
 #define        grub_memmove memmove
+#define grub_log2 fsig_log2
 
 extern char **fsig_disk_read_junk(void);
+unsigned long fsig_log2(unsigned long);
 
 #define        ERR_FSYS_CORRUPT 1
+#define        ERR_OUTSIDE_PART 1
 #define        ERR_SYMLINK_LOOP 1
 #define        ERR_FILELENGTH 1
-#define        ERR_BAD_FILETYPE 1
 #define        ERR_BAD_FILETYPE 1
 #define        ERR_FILE_NOT_FOUND 1
 
diff -r 9364bea18bc4 -r 202eb735b425 tools/libfsimage/common/mapfile-GNU
--- a/tools/libfsimage/common/mapfile-GNU       Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libfsimage/common/mapfile-GNU       Thu Feb 22 10:15:29 2007 -0700
@@ -20,6 +20,7 @@ VERSION {
                        fsig_init;
                        fsig_devread;
                        fsig_substring;
+                       fsig_log2;
                        fsig_fs_buf;
                        fsig_file_alloc;
                        fsig_file_buf;
diff -r 9364bea18bc4 -r 202eb735b425 tools/libfsimage/common/mapfile-SunOS
--- a/tools/libfsimage/common/mapfile-SunOS     Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libfsimage/common/mapfile-SunOS     Thu Feb 22 10:15:29 2007 -0700
@@ -19,6 +19,7 @@ libfsimage.so.1.0 {
                fsig_init;
                fsig_devread;
                fsig_substring;
+               fsig_log2;
                fsig_fs_buf;
                fsig_file_alloc;
                fsig_file_buf;
diff -r 9364bea18bc4 -r 202eb735b425 tools/libfsimage/ext2fs/fsys_ext2fs.c
--- a/tools/libfsimage/ext2fs/fsys_ext2fs.c     Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libfsimage/ext2fs/fsys_ext2fs.c     Thu Feb 22 10:15:29 2007 -0700
@@ -191,7 +191,7 @@ struct ext2_dir_entry
 
 
 /* ext2/super.c */
-#define log2(n) ffz(~(n))
+#define log2(n) grub_log2(n)
 
 #define EXT2_SUPER_MAGIC      0xEF53   /* include/linux/ext2_fs.h */
 #define EXT2_ROOT_INO              2   /* include/linux/ext2_fs.h */
@@ -231,93 +231,6 @@ struct ext2_dir_entry
 #define S_ISLNK(m)     (((m) & S_IFMT) == S_IFLNK)
 #define S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
 #define S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
-
-#if defined(__i386__) || defined(__x86_64__)
-/* include/asm-i386/bitops.h */
-/*
- * ffz = Find First Zero in word. Undefined if no zero exists,
- * so code should check against ~0UL first..
- */
-#ifdef __amd64
-#define BSF "bsfq"
-#else
-#define BSF "bsfl"
-#endif
-static __inline__ unsigned long
-ffz (unsigned long word)
-{
-  __asm__ (BSF " %1,%0"
-:         "=r" (word)
-:         "r" (~word));
-  return word;
-}
-
-#elif defined(__ia64__)
-
-typedef unsigned long __u64;
-
-#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
-# define ia64_popcnt(x) __builtin_popcountl(x)
-#else
-# define ia64_popcnt(x)                                     \
-  ({                                                        \
-    __u64 ia64_intri_res;                                   \
-    asm ("popcnt %0=%1" : "=r" (ia64_intri_res) : "r" (x)); \
-    ia64_intri_res;                                         \
-  })
-#endif
-
-static __inline__ unsigned long
-ffz (unsigned long word)
-{
-  unsigned long result;
-
-  result = ia64_popcnt(word & (~word - 1));
-  return result;
-}
-
-#elif defined(__powerpc__)
-
-#ifdef __powerpc64__
-#define PPC_CNTLZL "cntlzd"
-#else
-#define PPC_CNTLZL "cntlzw"
-#endif
-#define BITS_PER_LONG (sizeof(long) * 8)
-
-static __inline__ int
-__ilog2(unsigned long x)
-{
-  int lz;
-
-  asm (PPC_CNTLZL " %0,%1" : "=r" (lz) : "r" (x));
-  return BITS_PER_LONG - 1 - lz;
-}
-
-static __inline__ unsigned long
-ffz (unsigned long word)
-{
-  if ((word = ~word) == 0)
-    return BITS_PER_LONG;
-  return __ilog2(word & -word);
-}
-
-#else /* Unoptimized */
-
-static __inline__ unsigned long
-ffz (unsigned long word)
-{
-  unsigned long result;
-
-  result = 0;
-  while(word & 1)
-    {
-      result++;
-      word >>= 1;
-    }
-  return result;
-}
-#endif
 
 /* check filesystem types and read superblock into memory buffer */
 int
diff -r 9364bea18bc4 -r 202eb735b425 tools/libfsimage/fat/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libfsimage/fat/Makefile     Thu Feb 22 10:15:29 2007 -0700
@@ -0,0 +1,13 @@
+XEN_ROOT = ../../..
+
+LIB_SRCS-y = fsys_fat.c
+
+FS = fat
+
+.PHONY: all
+all: fs-all
+
+.PHONY: install
+install: fs-install
+
+include $(XEN_ROOT)/tools/libfsimage/Rules.mk
diff -r 9364bea18bc4 -r 202eb735b425 tools/libfsimage/fat/fat.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libfsimage/fat/fat.h        Thu Feb 22 10:15:29 2007 -0700
@@ -0,0 +1,100 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2001  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+ *  Defines for the FAT BIOS Parameter Block (embedded in the first block
+ *  of the partition.
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+/* Note that some shorts are not aligned, and must therefore
+ * be declared as array of two bytes.
+ */
+struct fat_bpb {
+       __s8    ignored[3];     /* Boot strap short or near jump */
+       __s8    system_id[8];   /* Name - can be used to special case
+                                  partition manager volumes */
+       __u8    bytes_per_sect[2];      /* bytes per logical sector */
+       __u8    sects_per_clust;/* sectors/cluster */
+       __u8    reserved_sects[2];      /* reserved sectors */
+       __u8    num_fats;       /* number of FATs */
+       __u8    dir_entries[2]; /* root directory entries */
+       __u8    short_sectors[2];       /* number of sectors */
+       __u8    media;          /* media code (unused) */
+       __u16   fat_length;     /* sectors/FAT */
+       __u16   secs_track;     /* sectors per track */
+       __u16   heads;          /* number of heads */
+       __u32   hidden;         /* hidden sectors (unused) */
+       __u32   long_sectors;   /* number of sectors (if short_sectors == 0) */
+
+       /* The following fields are only used by FAT32 */
+       __u32   fat32_length;   /* sectors/FAT */
+       __u16   flags;          /* bit 8: fat mirroring, low 4: active fat */
+       __u8    version[2];     /* major, minor filesystem version */
+       __u32   root_cluster;   /* first cluster in root directory */
+       __u16   info_sector;    /* filesystem info sector */
+       __u16   backup_boot;    /* backup boot sector */
+       __u16   reserved2[6];   /* Unused */
+};
+
+#define FAT_CVT_U16(bytarr) (* (__u16*)(bytarr))
+
+/*
+ *  Defines how to differentiate a 12-bit and 16-bit FAT.
+ */
+
+#define FAT_MAX_12BIT_CLUST       4087 /* 4085 + 2 */
+
+/*
+ *  Defines for the file "attribute" byte
+ */
+
+#define FAT_ATTRIB_OK_MASK        0x37
+#define FAT_ATTRIB_NOT_OK_MASK    0xC8
+#define FAT_ATTRIB_DIR            0x10
+#define FAT_ATTRIB_LONGNAME       0x0F
+
+/*
+ *  Defines for FAT directory entries
+ */
+
+#define FAT_DIRENTRY_LENGTH       32
+
+#define FAT_DIRENTRY_ATTRIB(entry) \
+  (*((unsigned char *) (entry+11)))
+#define FAT_DIRENTRY_VALID(entry) \
+  ( ((*((unsigned char *) entry)) != 0) \
+    && ((*((unsigned char *) entry)) != 0xE5) \
+    && !(FAT_DIRENTRY_ATTRIB(entry) & FAT_ATTRIB_NOT_OK_MASK) )
+#define FAT_DIRENTRY_FIRST_CLUSTER(entry) \
+  ((*((unsigned short *) (entry+26)))+(*((unsigned short *) (entry+20)) << 16))
+#define FAT_DIRENTRY_FILELENGTH(entry) \
+  (*((unsigned long *) (entry+28)))
+
+#define FAT_LONGDIR_ID(entry) \
+  (*((unsigned char *) (entry)))
+#define FAT_LONGDIR_ALIASCHECKSUM(entry) \
+  (*((unsigned char *) (entry+13)))
diff -r 9364bea18bc4 -r 202eb735b425 tools/libfsimage/fat/fsys_fat.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libfsimage/fat/fsys_fat.c   Thu Feb 22 10:15:29 2007 -0700
@@ -0,0 +1,485 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2000,2001,2005   Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <limits.h>
+#include <fsimage_grub.h>
+#include "fat.h"
+
+struct fat_superblock 
+{
+  int fat_offset;
+  int fat_length;
+  int fat_size;
+  int root_offset;
+  int root_max;
+  int data_offset;
+  
+  int num_sectors;
+  int num_clust;
+  int clust_eof_marker;
+  int sects_per_clust;
+  int sectsize_bits;
+  int clustsize_bits;
+  int root_cluster;
+  
+  int cached_fat;
+  int file_cluster;
+  int current_cluster_num;
+  int current_cluster;
+};
+
+/* pointer(s) into filesystem info buffer for DOS stuff */
+#define FAT_SUPER ( (struct fat_superblock *) \
+                   ( FSYS_BUF + 32256) )/* 512 bytes long */
+#define FAT_BUF   ( FSYS_BUF + 30208 ) /* 4 sector FAT buffer */
+#define NAME_BUF  ( FSYS_BUF + 29184 ) /* Filename buffer (833 bytes) */
+
+#define FAT_CACHE_SIZE 2048
+
+#define log2 grub_log2
+
+int
+fat_mount (fsi_file_t *ffi, const char *options)
+{
+  struct fat_bpb bpb;
+  __u32 magic, first_fat;
+  
+  /* Read bpb */
+  if (! devread (ffi, 0, 0, sizeof (bpb), (char *) &bpb))
+    return 0;
+
+  /* Check if the number of sectors per cluster is zero here, to avoid
+     zero division.  */
+  if (bpb.sects_per_clust == 0)
+    return 0;
+  
+  FAT_SUPER->sectsize_bits = log2 (FAT_CVT_U16 (bpb.bytes_per_sect));
+  FAT_SUPER->clustsize_bits
+    = FAT_SUPER->sectsize_bits + log2 (bpb.sects_per_clust);
+  
+  /* Fill in info about super block */
+  FAT_SUPER->num_sectors = FAT_CVT_U16 (bpb.short_sectors) 
+    ? FAT_CVT_U16 (bpb.short_sectors) : bpb.long_sectors;
+  
+  /* FAT offset and length */
+  FAT_SUPER->fat_offset = FAT_CVT_U16 (bpb.reserved_sects);
+  FAT_SUPER->fat_length = 
+    bpb.fat_length ? bpb.fat_length : bpb.fat32_length;
+  
+  /* Rootdir offset and length for FAT12/16 */
+  FAT_SUPER->root_offset = 
+    FAT_SUPER->fat_offset + bpb.num_fats * FAT_SUPER->fat_length;
+  FAT_SUPER->root_max = FAT_DIRENTRY_LENGTH * FAT_CVT_U16(bpb.dir_entries);
+  
+  /* Data offset and number of clusters */
+  FAT_SUPER->data_offset = 
+    FAT_SUPER->root_offset
+    + ((FAT_SUPER->root_max - 1) >> FAT_SUPER->sectsize_bits) + 1;
+  FAT_SUPER->num_clust = 
+    2 + ((FAT_SUPER->num_sectors - FAT_SUPER->data_offset) 
+        / bpb.sects_per_clust);
+  FAT_SUPER->sects_per_clust = bpb.sects_per_clust;
+  
+  if (!bpb.fat_length)
+    {
+      /* This is a FAT32 */
+      if (FAT_CVT_U16(bpb.dir_entries))
+       return 0;
+      
+      if (bpb.flags & 0x0080)
+       {
+         /* FAT mirroring is disabled, get active FAT */
+         int active_fat = bpb.flags & 0x000f;
+         if (active_fat >= bpb.num_fats)
+           return 0;
+         FAT_SUPER->fat_offset += active_fat * FAT_SUPER->fat_length;
+       }
+      
+      FAT_SUPER->fat_size = 8;
+      FAT_SUPER->root_cluster = bpb.root_cluster;
+
+      /* Yes the following is correct.  FAT32 should be called FAT28 :) */
+      FAT_SUPER->clust_eof_marker = 0xffffff8;
+    } 
+  else 
+    {
+      if (!FAT_SUPER->root_max)
+       return 0;
+      
+      FAT_SUPER->root_cluster = -1;
+      if (FAT_SUPER->num_clust > FAT_MAX_12BIT_CLUST) 
+       {
+         FAT_SUPER->fat_size = 4;
+         FAT_SUPER->clust_eof_marker = 0xfff8;
+       } 
+      else
+       {
+         FAT_SUPER->fat_size = 3;
+         FAT_SUPER->clust_eof_marker = 0xff8;
+       }
+    }
+
+  /* Now do some sanity checks */
+  
+  if (FAT_CVT_U16(bpb.bytes_per_sect) != (1 << FAT_SUPER->sectsize_bits)
+      || FAT_CVT_U16(bpb.bytes_per_sect) != SECTOR_SIZE
+      || bpb.sects_per_clust != (1 << (FAT_SUPER->clustsize_bits
+                                      - FAT_SUPER->sectsize_bits))
+      || FAT_SUPER->num_clust <= 2
+      || (FAT_SUPER->fat_size * FAT_SUPER->num_clust / (2 * SECTOR_SIZE)
+         > FAT_SUPER->fat_length))
+    return 0;
+  
+  /* kbs: Media check on first FAT entry [ported from PUPA] */
+
+  if (!devread(ffi, FAT_SUPER->fat_offset, 0,
+               sizeof(first_fat), (char *)&first_fat))
+    return 0;
+
+  if (FAT_SUPER->fat_size == 8)
+    {
+      first_fat &= 0x0fffffff;
+      magic = 0x0fffff00;
+    }
+  else if (FAT_SUPER->fat_size == 4)
+    {
+      first_fat &= 0x0000ffff;
+      magic = 0xff00;
+    }
+  else
+    {
+      first_fat &= 0x00000fff;
+      magic = 0x0f00;
+    }
+
+  /* Ignore the 3rd bit, because some BIOSes assigns 0xF0 to the media
+     descriptor, even if it is a so-called superfloppy (e.g. an USB key).
+     The check may be too strict for this kind of stupid BIOSes, as
+     they overwrite the media descriptor.  */
+  if ((first_fat | 0x8) != (magic | bpb.media | 0x8))
+    return 0;
+
+  FAT_SUPER->cached_fat = - 2 * FAT_CACHE_SIZE;
+  return 1;
+}
+
+int
+fat_read (fsi_file_t *ffi, char *buf, int len)
+{
+  int logical_clust;
+  int offset;
+  int ret = 0;
+  int size;
+  
+  if (FAT_SUPER->file_cluster < 0)
+    {
+      /* root directory for fat16 */
+      size = FAT_SUPER->root_max - filepos;
+      if (size > len)
+       size = len;
+      if (!devread(ffi, FAT_SUPER->root_offset, filepos, size, buf))
+       return 0;
+      filepos += size;
+      return size;
+    }
+  
+  logical_clust = filepos >> FAT_SUPER->clustsize_bits;
+  offset = (filepos & ((1 << FAT_SUPER->clustsize_bits) - 1));
+  if (logical_clust < FAT_SUPER->current_cluster_num)
+    {
+      FAT_SUPER->current_cluster_num = 0;
+      FAT_SUPER->current_cluster = FAT_SUPER->file_cluster;
+    }
+  
+  while (len > 0)
+    {
+      int sector;
+      while (logical_clust > FAT_SUPER->current_cluster_num)
+       {
+         /* calculate next cluster */
+         int fat_entry = 
+           FAT_SUPER->current_cluster * FAT_SUPER->fat_size;
+         int next_cluster;
+         int cached_pos = (fat_entry - FAT_SUPER->cached_fat);
+         
+         if (cached_pos < 0 || 
+             (cached_pos + FAT_SUPER->fat_size) > 2*FAT_CACHE_SIZE)
+           {
+             FAT_SUPER->cached_fat = (fat_entry & ~(2*SECTOR_SIZE - 1));
+             cached_pos = (fat_entry - FAT_SUPER->cached_fat);
+             sector = FAT_SUPER->fat_offset
+               + FAT_SUPER->cached_fat / (2*SECTOR_SIZE);
+             if (!devread (ffi, sector, 0, FAT_CACHE_SIZE, (char*) FAT_BUF))
+               return 0;
+           }
+         next_cluster = * (unsigned long *) (FAT_BUF + (cached_pos >> 1));
+         if (FAT_SUPER->fat_size == 3)
+           {
+             if (cached_pos & 1)
+               next_cluster >>= 4;
+             next_cluster &= 0xFFF;
+           }
+         else if (FAT_SUPER->fat_size == 4)
+           next_cluster &= 0xFFFF;
+         
+         if (next_cluster >= FAT_SUPER->clust_eof_marker)
+           return ret;
+         if (next_cluster < 2 || next_cluster >= FAT_SUPER->num_clust)
+           {
+             errnum = ERR_FSYS_CORRUPT;
+             return 0;
+           }
+         
+         FAT_SUPER->current_cluster = next_cluster;
+         FAT_SUPER->current_cluster_num++;
+       }
+      
+      sector = FAT_SUPER->data_offset +
+       ((FAT_SUPER->current_cluster - 2) << (FAT_SUPER->clustsize_bits
+                                             - FAT_SUPER->sectsize_bits));
+      size = (1 << FAT_SUPER->clustsize_bits) - offset;
+      if (size > len)
+       size = len;
+      
+      disk_read_func = disk_read_hook;
+      
+      devread(ffi, sector, offset, size, buf);
+      
+      disk_read_func = NULL;
+      
+      len -= size;
+      buf += size;
+      ret += size;
+      filepos += size;
+      logical_clust++;
+      offset = 0;
+    }
+  return errnum ? 0 : ret;
+}
+
+int
+fat_dir (fsi_file_t *ffi, char *dirname)
+{
+  char *rest, ch, dir_buf[FAT_DIRENTRY_LENGTH];
+  char *filename = (char *) NAME_BUF;
+  int attrib = FAT_ATTRIB_DIR;
+#ifndef STAGE1_5
+  int do_possibilities = 0;
+#endif
+  
+  /* XXX I18N:
+   * the positions 2,4,6 etc are high bytes of a 16 bit unicode char 
+   */
+  static unsigned char longdir_pos[] = 
+  { 1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30 };
+  int slot = -2;
+  int alias_checksum = -1;
+  
+  FAT_SUPER->file_cluster = FAT_SUPER->root_cluster;
+  filepos = 0;
+  FAT_SUPER->current_cluster_num = INT_MAX;
+  
+  /* main loop to find desired directory entry */
+ loop:
+  
+  /* if we have a real file (and we're not just printing possibilities),
+     then this is where we want to exit */
+  
+  if (!*dirname || isspace (*dirname))
+    {
+      if (attrib & FAT_ATTRIB_DIR)
+       {
+         errnum = ERR_BAD_FILETYPE;
+         return 0;
+       }
+      
+      return 1;
+    }
+  
+  /* continue with the file/directory name interpretation */
+  
+  while (*dirname == '/')
+    dirname++;
+  
+  if (!(attrib & FAT_ATTRIB_DIR))
+    {
+      errnum = ERR_BAD_FILETYPE;
+      return 0;
+    }
+  /* Directories don't have a file size */
+  filemax = INT_MAX;
+  
+  for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
+  
+  *rest = 0;
+  
+# ifndef STAGE1_5
+  if (print_possibilities && ch != '/')
+    do_possibilities = 1;
+# endif
+  
+  while (1)
+    {
+      if (fat_read (ffi, dir_buf, FAT_DIRENTRY_LENGTH) != FAT_DIRENTRY_LENGTH
+         || dir_buf[0] == 0)
+       {
+         if (!errnum)
+           {
+# ifndef STAGE1_5
+             if (print_possibilities < 0)
+               {
+#if 0
+                 putchar ('\n');
+#endif
+                 return 1;
+               }
+# endif /* STAGE1_5 */
+             
+             errnum = ERR_FILE_NOT_FOUND;
+             *rest = ch;
+           }
+         
+         return 0;
+       }
+      
+      if (FAT_DIRENTRY_ATTRIB (dir_buf) == FAT_ATTRIB_LONGNAME)
+       {
+         /* This is a long filename.  The filename is build from back
+          * to front and may span multiple entries.  To bind these
+          * entries together they all contain the same checksum over
+          * the short alias.
+          *
+          * The id field tells if this is the first entry (the last
+          * part) of the long filename, and also at which offset this
+          * belongs.
+          *
+          * We just write the part of the long filename this entry
+          * describes and continue with the next dir entry.
+          */
+         int i, offset;
+         unsigned char id = FAT_LONGDIR_ID(dir_buf);
+         
+         if ((id & 0x40)) 
+           {
+             id &= 0x3f;
+             slot = id;
+             filename[slot * 13] = 0;
+             alias_checksum = FAT_LONGDIR_ALIASCHECKSUM(dir_buf);
+           } 
+         
+         if (id != slot || slot == 0
+             || alias_checksum != FAT_LONGDIR_ALIASCHECKSUM(dir_buf))
+           {
+             alias_checksum = -1;
+             continue;
+           }
+         
+         slot--;
+         offset = slot * 13;
+         
+         for (i=0; i < 13; i++)
+           filename[offset+i] = dir_buf[longdir_pos[i]];
+         continue;
+       }
+      
+      if (!FAT_DIRENTRY_VALID (dir_buf))
+       continue;
+      
+      if (alias_checksum != -1 && slot == 0)
+       {
+         int i;
+         unsigned char sum;
+         
+         slot = -2;
+         for (sum = 0, i = 0; i< 11; i++)
+           sum = ((sum >> 1) | (sum << 7)) + dir_buf[i];
+         
+         if (sum == alias_checksum)
+           {
+# ifndef STAGE1_5
+             if (do_possibilities)
+               goto print_filename;
+# endif /* STAGE1_5 */
+             
+             if (substring (dirname, filename) == 0)
+               break;
+           }
+       }
+      
+      /* XXX convert to 8.3 filename format here */
+      {
+       int i, j, c;
+       
+       for (i = 0; i < 8 && (c = filename[i] = tolower (dir_buf[i]))
+              && !isspace (c); i++);
+       
+       filename[i++] = '.';
+       
+       for (j = 0; j < 3 && (c = filename[i + j] = tolower (dir_buf[8 + j]))
+              && !isspace (c); j++);
+       
+       if (j == 0)
+         i--;
+       
+       filename[i + j] = 0;
+      }
+      
+# ifndef STAGE1_5
+      if (do_possibilities)
+       {
+       print_filename:
+         if (substring (dirname, filename) <= 0)
+           {
+             if (print_possibilities > 0)
+               print_possibilities = -print_possibilities;
+             print_a_completion (filename);
+           }
+         continue;
+       }
+# endif /* STAGE1_5 */
+      
+      if (substring (dirname, filename) == 0)
+       break;
+    }
+  
+  *(dirname = rest) = ch;
+  
+  attrib = FAT_DIRENTRY_ATTRIB (dir_buf);
+  filemax = FAT_DIRENTRY_FILELENGTH (dir_buf);
+  filepos = 0;
+  FAT_SUPER->file_cluster = FAT_DIRENTRY_FIRST_CLUSTER (dir_buf);
+  FAT_SUPER->current_cluster_num = INT_MAX;
+  
+  /* go back to main loop at top of function */
+  goto loop;
+}
+
+fsi_plugin_ops_t *
+fsi_init_plugin(int version, fsi_plugin_t *fp, const char **name)
+{
+       static fsig_plugin_ops_t ops = {
+               FSIMAGE_PLUGIN_VERSION,
+               .fpo_mount = fat_mount,
+               .fpo_dir = fat_dir,
+               .fpo_read = fat_read
+       };
+
+       *name = "fat";
+       return (fsig_init(fp, &ops));
+}
diff -r 9364bea18bc4 -r 202eb735b425 tools/libfsimage/iso9660/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libfsimage/iso9660/Makefile Thu Feb 22 10:15:29 2007 -0700
@@ -0,0 +1,15 @@
+XEN_ROOT = ../../..
+
+LIB_SRCS-y = fsys_iso9660.c
+
+FS = iso9660
+
+.PHONY: all
+all: fs-all
+
+.PHONY: install
+install: fs-install
+
+fsys_iso9660.c: iso9660.h
+
+include $(XEN_ROOT)/tools/libfsimage/Rules.mk
diff -r 9364bea18bc4 -r 202eb735b425 tools/libfsimage/iso9660/fsys_iso9660.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libfsimage/iso9660/fsys_iso9660.c   Thu Feb 22 10:15:29 2007 -0700
@@ -0,0 +1,463 @@
+/*
+ *  ISO 9660 filesystem backend for GRUB (GRand Unified Bootloader)
+ *  including Rock Ridge Extensions support
+ *
+ *  Copyright (C) 1998, 1999  Kousuke Takai  <tak@xxxxxxxxxxxxxxxxx>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ *  References:
+ *     linux/fs/isofs/rock.[ch]
+ *     mkisofs-1.11.1/diag/isoinfo.c
+ *     mkisofs-1.11.1/iso9660.h
+ *             (all are written by Eric Youngdale)
+ *
+ *  Modifications by:
+ *     Leonid Lisovskiy   <lly@xxxxxxxxx>      2003
+ */
+
+#include <fsimage_grub.h>
+#include <limits.h>
+
+#include "iso9660.h"
+
+#define        MAXINT INT_MAX
+
+/* iso9660 super-block data in memory */
+struct iso_sb_info {
+  unsigned long vol_sector;
+
+};
+
+/* iso fs inode data in memory */
+struct iso_inode_info {
+  unsigned long file_start;
+};
+
+#define ISO_SUPER      \
+    ((struct iso_sb_info *)(FSYS_BUF))
+#define INODE          \
+    ((struct iso_inode_info *)(FSYS_BUF+sizeof(struct iso_sb_info)))
+#define PRIMDESC        ((struct iso_primary_descriptor *)(FSYS_BUF + 2048))
+#define DIRREC          ((struct iso_directory_record *)(FSYS_BUF + 4096))
+#define RRCONT_BUF      ((unsigned char *)(FSYS_BUF + 6144))
+#define NAME_BUF        ((unsigned char *)(FSYS_BUF + 8192))
+
+
+#define log2 grub_log2
+
+static int
+iso9660_devread (fsi_file_t *ffi, int sector, int byte_offset, int byte_len, 
char *buf)
+{
+  static int read_count = 0, threshold = 2;
+  unsigned short sector_size_lg2 = log2(512 /*buf_geom.sector_size*/);
+
+  /*
+   * We have to use own devread() function since BIOS return wrong geometry
+   */
+  if (sector < 0)
+    {
+      errnum = ERR_OUTSIDE_PART;
+      return 0;
+    }
+  if (byte_len <= 0)
+    return 1;
+
+#if 0
+  sector += (byte_offset >> sector_size_lg2);
+  byte_offset &= (buf_geom.sector_size - 1);
+  asm volatile ("shl%L0 %1,%0"
+               : "=r"(sector)
+               : "Ic"((int8_t)(ISO_SECTOR_BITS - sector_size_lg2)),
+               "0"(sector));
+#else
+  sector = (sector * 4) + (byte_offset >> sector_size_lg2);
+  byte_offset &= 511;
+#endif
+
+#if !defined(STAGE1_5)
+  if (disk_read_hook && debug)
+    printf ("<%d, %d, %d>", sector, byte_offset, byte_len);
+#endif /* !STAGE1_5 */
+
+  read_count += (byte_len >> 9);
+  if ((read_count >> 11) > threshold) {
+       noisy_printf(".");
+       threshold += 2; /* one dot every 2 MB */
+  }
+  return devread(ffi, sector, byte_offset, byte_len, buf);
+}
+
+int
+iso9660_mount (fsi_file_t *ffi, const char *options)
+{
+  unsigned int sector;
+
+  /*
+   *  Because there is no defined slice type ID for ISO-9660 filesystem,
+   *  this test will pass only either (1) if entire disk is used, or
+   *  (2) if current partition is BSD style sub-partition whose ID is
+   *  ISO-9660.
+   */
+#if 0
+  if ((current_partition != 0xFFFFFF)
+      && !IS_PC_SLICE_TYPE_BSD_WITH_FS(current_slice, FS_ISO9660))
+    return 0;
+#endif
+
+  /*
+   *  Currently, only FIRST session of MultiSession disks are supported !!!
+   */
+  for (sector = 16 ; sector < 32 ; sector++)
+    {
+      if (!iso9660_devread(ffi, sector, 0, sizeof(*PRIMDESC), (char 
*)PRIMDESC)) 
+       break;
+      /* check ISO_VD_PRIMARY and ISO_STANDARD_ID */
+      if (PRIMDESC->type.l == ISO_VD_PRIMARY
+         && !memcmp(PRIMDESC->id, ISO_STANDARD_ID, sizeof(PRIMDESC->id)))
+       {
+         ISO_SUPER->vol_sector = sector;
+         INODE->file_start = 0;
+#if 0
+         fsmax = PRIMDESC->volume_space_size.l;
+#endif
+         return 1;
+       }
+    }
+
+  return 0;
+}
+
+int
+iso9660_dir (fsi_file_t *ffi, char *dirname)
+{
+  struct iso_directory_record *idr;
+  RR_ptr_t rr_ptr;
+  struct rock_ridge *ce_ptr;
+  unsigned int pathlen;
+  int size;
+  unsigned int extent;
+  unsigned char file_type;
+  unsigned int rr_len;
+  unsigned char rr_flag;
+
+  idr = &PRIMDESC->root_directory_record;
+  INODE->file_start = 0;
+
+  do
+    {
+      while (*dirname == '/')  /* skip leading slashes */
+       dirname++;
+      /* pathlen = strcspn(dirname, "/\n\t "); */
+      for (pathlen = 0 ;
+          dirname[pathlen]
+            && !isspace(dirname[pathlen]) && dirname[pathlen] != '/' ;
+          pathlen++)
+       ;
+
+      size = idr->size.l;
+      extent = idr->extent.l;
+
+      while (size > 0)
+       {
+         if (!iso9660_devread(ffi, extent, 0, ISO_SECTOR_SIZE, (char *)DIRREC))
+           {
+             errnum = ERR_FSYS_CORRUPT;
+             return 0;
+           }
+         extent++;
+
+         idr = (struct iso_directory_record *)DIRREC;
+         for (; idr->length.l > 0;
+              idr = (struct iso_directory_record *)((char *)idr + 
idr->length.l) )
+           {
+             const char *name = (const char *)idr->name;
+             unsigned int name_len = idr->name_len.l;
+
+             file_type = (idr->flags.l & 2) ? ISO_DIRECTORY : ISO_REGULAR;
+             if (name_len == 1)
+               {
+                 if ((name[0] == 0) || /* self */
+                     (name[0] == 1))   /* parent */
+                   continue;
+               }
+             if (name_len > 2 && CHECK2(name + name_len - 2, ';', '1'))
+               {
+                 name_len -= 2;        /* truncate trailing file version */
+                 if (name_len > 1 && name[name_len - 1] == '.')
+                   name_len--;         /* truncate trailing dot */
+               }
+
+             /*
+              *  Parse Rock-Ridge extension
+              */
+             rr_len = (idr->length.l - idr->name_len.l
+                       - sizeof(struct iso_directory_record)
+                       + sizeof(idr->name));
+             rr_ptr.ptr = ((char *)idr + idr->name_len.l
+                           + sizeof(struct iso_directory_record)
+                           - sizeof(idr->name));
+             if (rr_ptr.i & 1)
+               rr_ptr.i++, rr_len--;
+             ce_ptr = NULL;
+             rr_flag = RR_FLAG_NM | RR_FLAG_PX /*| RR_FLAG_SL*/;
+
+             while (rr_len >= 4)
+               {
+                 if (rr_ptr.rr->version != 1)
+                   {
+#ifndef STAGE1_5
+                     if (debug)
+                       printf(
+                              "Non-supported version (%d) RockRidge chunk "
+                              "`%c%c'\n", rr_ptr.rr->version,
+                              rr_ptr.rr->signature & 0xFF,
+                              rr_ptr.rr->signature >> 8);
+#endif
+                   }
+                 else
+                   {
+                     switch (rr_ptr.rr->signature)
+                       {
+                       case RRMAGIC('R', 'R'):
+                         if ( rr_ptr.rr->len >= (4+sizeof(struct RR)))
+                           rr_flag &= rr_ptr.rr->u.rr.flags.l;
+                         break;
+                       case RRMAGIC('N', 'M'):
+                         name = (const char *)rr_ptr.rr->u.nm.name;
+                         name_len = rr_ptr.rr->len - (4+sizeof(struct NM));
+                         rr_flag &= ~RR_FLAG_NM;
+                         break;
+                       case RRMAGIC('P', 'X'):
+                         if (rr_ptr.rr->len >= (4+sizeof(struct PX)))
+                           {
+                             file_type = ((rr_ptr.rr->u.px.mode.l & 
POSIX_S_IFMT)
+                                          == POSIX_S_IFREG
+                                          ? ISO_REGULAR
+                                          : ((rr_ptr.rr->u.px.mode.l & 
POSIX_S_IFMT)
+                                             == POSIX_S_IFDIR
+                                             ? ISO_DIRECTORY : ISO_OTHER));
+                             rr_flag &= ~RR_FLAG_PX;
+                           }
+                         break;
+                       case RRMAGIC('C', 'E'):
+                         if (rr_ptr.rr->len >= (4+sizeof(struct CE)))
+                           ce_ptr = rr_ptr.rr;
+                         break;
+#if 0          // RockRidge symlinks are not supported yet
+                       case RRMAGIC('S', 'L'):
+                         {
+                           int slen;
+                           unsigned char rootflag, prevflag;
+                           char *rpnt = NAME_BUF+1024;
+                           struct SL_component *slp;
+
+                           slen = rr_ptr.rr->len - (4+1);
+                           slp = &rr_ptr.rr->u.sl.link;
+                           while (slen > 1)
+                             {
+                               rootflag = 0;
+                               switch (slp->flags.l)
+                                 {
+                                 case 0:
+                                   memcpy(rpnt, slp->text, slp->len);
+                                   rpnt += slp->len;
+                                   break;
+                                 case 4:
+                                   *rpnt++ = '.';
+                                   /* fallthru */
+                                 case 2:
+                                   *rpnt++ = '.';
+                                   break;
+                                 case 8:
+                                   rootflag = 1;
+                                   *rpnt++ = '/';
+                                   break;
+                                 default:
+                                   printf("Symlink component flag not 
implemented (%d)\n",
+                                          slp->flags.l);
+                                   slen = 0;
+                                   break;
+                                 }
+                               slen -= slp->len + 2;
+                               prevflag = slp->flags.l;
+                               slp = (struct SL_component *) ((char *) slp + 
slp->len + 2);
+
+                               if (slen < 2)
+                                 {
+                                   /*
+                                    * If there is another SL record, and this 
component
+                                    * record isn't continued, then add a slash.
+                                    */
+                                   if ((!rootflag) && (rr_ptr.rr->u.sl.flags.l 
& 1) && !(prevflag & 1))
+                                     *rpnt++='/';
+                                   break;
+                                 }
+
+                               /*
+                                * If this component record isn't continued, 
then append a '/'.
+                                */
+                               if (!rootflag && !(prevflag & 1))
+                                 *rpnt++ = '/';
+                             }
+                           *rpnt++ = '\0';
+                           grub_putstr(NAME_BUF+1024);// debug print!
+                         }
+                         rr_flag &= ~RR_FLAG_SL;
+                         break;
+#endif
+                       default:
+                         break;
+                       }
+                   }
+                 if (!rr_flag)
+                   /*
+                    * There is no more extension we expects...
+                    */
+                   break;
+
+                 rr_len -= rr_ptr.rr->len;
+                 rr_ptr.ptr += rr_ptr.rr->len;
+                 if (rr_len < 4 && ce_ptr != NULL)
+                   {
+                     /* preserve name before loading new extent. */
+                     if( RRCONT_BUF <= (unsigned char *)name
+                         && (unsigned char *)name < RRCONT_BUF + 
ISO_SECTOR_SIZE )
+                       {
+                         memcpy(NAME_BUF, name, name_len);
+                         name = (const char *)NAME_BUF;
+                       }
+                     rr_ptr.ptr = (char *)RRCONT_BUF + ce_ptr->u.ce.offset.l;
+                     rr_len = ce_ptr->u.ce.size.l;
+                     if (!iso9660_devread(ffi, ce_ptr->u.ce.extent.l, 0, 
ISO_SECTOR_SIZE, (char *)RRCONT_BUF))
+                       {
+                         errnum = 0;   /* this is not fatal. */
+                         break;
+                       }
+                     ce_ptr = NULL;
+                   }
+               } /* rr_len >= 4 */
+
+             filemax = MAXINT;
+             if (name_len >= pathlen
+                 && !memcmp(name, dirname, pathlen))
+               {
+                 if (dirname[pathlen] == '/' || !print_possibilities)
+                   {
+                     /*
+                      *  DIRNAME is directory component of pathname,
+                      *  or we are to open a file.
+                      */
+                     if (pathlen == name_len)
+                       {
+                         if (dirname[pathlen] == '/')
+                           {
+                             if (file_type != ISO_DIRECTORY)
+                               {
+                                 errnum = ERR_BAD_FILETYPE;
+                                 return 0;
+                               }
+                             goto next_dir_level;
+                           }
+                         if (file_type != ISO_REGULAR)
+                           {
+                             errnum = ERR_BAD_FILETYPE;
+                             return 0;
+                           }
+                         INODE->file_start = idr->extent.l;
+                         filepos = 0;
+                         filemax = idr->size.l;
+                         return 1;
+                       }
+                   }
+                 else  /* Completion */
+                   {
+#ifndef STAGE1_5
+                     if (print_possibilities > 0)
+                       print_possibilities = -print_possibilities;
+                     memcpy(NAME_BUF, name, name_len);
+                     NAME_BUF[name_len] = '\0';
+                     print_a_completion (NAME_BUF);
+#endif
+                   }
+               }
+           } /* for */
+
+         size -= ISO_SECTOR_SIZE;
+       } /* size>0 */
+
+      if (dirname[pathlen] == '/' || print_possibilities >= 0)
+       {
+         errnum = ERR_FILE_NOT_FOUND;
+         return 0;
+       }
+
+    next_dir_level:
+      dirname += pathlen;
+
+    } while (*dirname == '/');
+
+  return 1;
+}
+
+int
+iso9660_read (fsi_file_t *ffi, char *buf, int len)
+{
+  int sector, blkoffset, size, ret;
+
+  if (INODE->file_start == 0)
+    return 0;
+
+  ret = 0;
+  blkoffset = filepos & (ISO_SECTOR_SIZE - 1);
+  sector = filepos >> ISO_SECTOR_BITS;
+  while (len > 0)
+    {
+      size = ISO_SECTOR_SIZE - blkoffset;
+      if (size > len)
+        size = len;
+
+      disk_read_func = disk_read_hook;
+
+      if (!iso9660_devread(ffi, INODE->file_start + sector, blkoffset, size, 
buf))
+       return 0;
+
+      disk_read_func = NULL;
+
+      len -= size;
+      buf += size;
+      ret += size;
+      filepos += size;
+      sector++;
+      blkoffset = 0;
+    }
+
+  return ret;
+}
+
+fsi_plugin_ops_t *
+fsi_init_plugin(int version, fsi_plugin_t *fp, const char **name)
+{
+       static fsig_plugin_ops_t ops = {
+               FSIMAGE_PLUGIN_VERSION,
+               .fpo_mount = iso9660_mount,
+               .fpo_dir = iso9660_dir,
+               .fpo_read = iso9660_read
+       };
+
+       *name = "iso9660";
+       return (fsig_init(fp, &ops));
+}
diff -r 9364bea18bc4 -r 202eb735b425 tools/libfsimage/iso9660/iso9660.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libfsimage/iso9660/iso9660.h        Thu Feb 22 10:15:29 2007 -0700
@@ -0,0 +1,219 @@
+/*
+ *  ISO 9660 filesystem backend for GRUB (GRand Unified Bootloader)
+ *  including Rock Ridge Extensions support
+ *
+ *  Copyright (C) 1998, 1999  Kousuke Takai  <tak@xxxxxxxxxxxxxxxxx>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ *  References:
+ *     linux/fs/isofs/rock.[ch]
+ *     mkisofs-1.11.1/diag/isoinfo.c
+ *     mkisofs-1.11.1/iso9660.h
+ *             (all are written by Eric Youngdale)
+ */
+
+#ifndef _ISO9660_H_
+#define _ISO9660_H_
+
+#define ISO_SECTOR_BITS              (11)
+#define ISO_SECTOR_SIZE              (1<<ISO_SECTOR_BITS)
+
+#define        ISO_REGULAR     1       /* regular file */
+#define        ISO_DIRECTORY   2       /* directory    */
+#define        ISO_OTHER       0       /* other file (with Rock Ridge) */
+
+#define        RR_FLAG_PX      0x01    /* have POSIX file attributes */
+#define RR_FLAG_PN     0x02    /* POSIX devices */
+#define RR_FLAG_SL     0x04    /* Symbolic link */
+#define        RR_FLAG_NM      0x08    /* have alternate file name   */
+#define RR_FLAG_CL     0x10    /* Child link */
+#define RR_FLAG_PL     0x20    /* Parent link */
+#define RR_FLAG_RE     0x40    /* Relocation directory */
+#define RR_FLAG_TF     0x80    /* Timestamps */
+
+/* POSIX file attributes for Rock Ridge extensions */
+#define        POSIX_S_IFMT    0xF000
+#define        POSIX_S_IFREG   0x8000
+#define        POSIX_S_IFDIR   0x4000
+
+/* volume descriptor types */
+#define ISO_VD_PRIMARY 1
+#define ISO_VD_END 255
+
+#define ISO_STANDARD_ID "CD001"
+
+#ifndef ASM_FILE
+
+#ifndef __sun
+#ifndef        __BIT_TYPES_DEFINED__
+typedef                 int     int8_t __attribute__((mode(QI)));
+typedef unsigned int   u_int8_t        __attribute__((mode(QI)));
+typedef                 int    int16_t __attribute__((mode(HI)));
+typedef unsigned int  u_int16_t        __attribute__((mode(HI)));
+typedef                 int    int32_t __attribute__((mode(SI)));
+typedef unsigned int  u_int32_t        __attribute__((mode(SI)));
+#endif
+#else
+#ifndef GRUB_UTIL
+typedef                 char  int8_t;
+typedef                 short int16_t;
+typedef                 int   int32_t;
+#endif /* ! GRUB_UTIL */
+typedef unsigned char  u_int8_t;
+typedef unsigned short u_int16_t;
+typedef unsigned int   u_int32_t;
+#endif /* __sun */
+
+typedef        union {
+  u_int8_t l,b;
+}      iso_8bit_t;
+
+struct __iso_16bit {
+  u_int16_t l, b;
+} __attribute__ ((packed));
+typedef        struct __iso_16bit iso_16bit_t;
+
+struct __iso_32bit {
+  u_int32_t l, b;
+} __attribute__ ((packed));
+typedef        struct __iso_32bit iso_32bit_t;
+
+typedef u_int8_t               iso_date_t[7];
+
+struct iso_directory_record {
+  iso_8bit_t   length;
+  iso_8bit_t   ext_attr_length;
+  iso_32bit_t  extent;
+  iso_32bit_t  size;
+  iso_date_t   date;
+  iso_8bit_t   flags;
+  iso_8bit_t   file_unit_size;
+  iso_8bit_t   interleave;
+  iso_16bit_t  volume_seq_number;
+  iso_8bit_t   name_len;
+  u_int8_t     name[1];
+} __attribute__ ((packed));
+
+struct iso_primary_descriptor {
+  iso_8bit_t   type;
+  u_int8_t     id[5];
+  iso_8bit_t   version;
+  u_int8_t     _unused1[1];
+  u_int8_t     system_id[32];
+  u_int8_t     volume_id[32];
+  u_int8_t     _unused2[8];
+  iso_32bit_t  volume_space_size;
+  u_int8_t     _unused3[32];
+  iso_16bit_t  volume_set_size;
+  iso_16bit_t  volume_seq_number;
+  iso_16bit_t  logical_block_size;
+  iso_32bit_t  path_table_size;
+  u_int8_t     type_l_path_table[4];
+  u_int8_t     opt_type_l_path_table[4];
+  u_int8_t     type_m_path_table[4];
+  u_int8_t     opt_type_m_path_table[4];
+  struct iso_directory_record root_directory_record;
+  u_int8_t     volume_set_id[128];
+  u_int8_t     publisher_id[128];
+  u_int8_t     preparer_id[128];
+  u_int8_t     application_id[128];
+  u_int8_t     copyright_file_id[37];
+  u_int8_t     abstract_file_id[37];
+  u_int8_t     bibliographic_file_id[37];
+  u_int8_t     creation_date[17];
+  u_int8_t     modification_date[17];
+  u_int8_t     expiration_date[17];
+  u_int8_t     effective_date[17];
+  iso_8bit_t   file_structure_version;
+  u_int8_t     _unused4[1];
+  u_int8_t     application_data[512];
+  u_int8_t     _unused5[653];
+} __attribute__ ((packed));
+
+struct rock_ridge {
+  u_int16_t    signature;
+  u_int8_t     len;
+  u_int8_t     version;
+  union {
+    struct SP {
+      u_int16_t        magic;
+      u_int8_t skip;
+    } sp;
+    struct CE {
+      iso_32bit_t      extent;
+      iso_32bit_t      offset;
+      iso_32bit_t      size;
+    } ce;
+    struct ER {
+      u_int8_t len_id;
+      u_int8_t len_des;
+      u_int8_t len_src;
+      u_int8_t ext_ver;
+      u_int8_t data[0];
+    } er;
+    struct RR {
+      iso_8bit_t       flags;
+    } rr;
+    struct PX {
+      iso_32bit_t      mode;
+      iso_32bit_t      nlink;
+      iso_32bit_t      uid;
+      iso_32bit_t      gid;
+    } px;
+    struct PN {
+      iso_32bit_t      dev_high;
+      iso_32bit_t      dev_low;
+    } pn;
+    struct SL {
+      iso_8bit_t flags;
+      struct SL_component {
+       iso_8bit_t      flags;
+       u_int8_t                len;
+       u_int8_t                text[0];
+      } link;
+    } sl;
+    struct NM {
+      iso_8bit_t       flags;
+      u_int8_t name[0];
+    } nm;
+    struct CL {
+      iso_32bit_t      location;
+    } cl;
+    struct PL {
+      iso_32bit_t      location;
+    } pl;
+    struct TF {
+      iso_8bit_t       flags;
+      iso_date_t       times[0];
+    } tf;
+  } u;
+} __attribute__ ((packed));
+
+typedef        union RR_ptr {
+  struct rock_ridge *rr;
+  char           *ptr;
+  int             i;
+} RR_ptr_t;
+
+#define        RRMAGIC(c1, c2) ((c1)|(c2) << 8)
+
+#define        CHECK2(ptr, c1, c2) \
+       (*(unsigned short *)(ptr) == (((c1) | (c2) << 8) & 0xFFFF))
+
+#endif /* !ASM_FILE */
+
+#endif /* _ISO9660_H_ */
diff -r 9364bea18bc4 -r 202eb735b425 tools/libfsimage/reiserfs/fsys_reiserfs.c
--- a/tools/libfsimage/reiserfs/fsys_reiserfs.c Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libfsimage/reiserfs/fsys_reiserfs.c Thu Feb 22 10:15:29 2007 -0700
@@ -363,83 +363,6 @@ struct fsys_reiser_info
 #define JOURNAL_START    ((__u32 *) (INFO + 1))
 #define JOURNAL_END      ((__u32 *) (FSYS_BUF + FSYS_BUFLEN))
 
-#if defined(__i386__) || defined(__x86_64__)
-
-#ifdef __amd64
-#define BSF "bsfq"
-#else
-#define BSF "bsfl"
-#endif
-static __inline__ unsigned long
-grub_log2 (unsigned long word)
-{
-  __asm__ (BSF " %1,%0"
-          : "=r" (word)
-          : "r" (word));
-  return word;
-}
-
-#elif defined(__ia64__)
-
-#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
-# define ia64_popcnt(x) __builtin_popcountl(x)
-#else
-# define ia64_popcnt(x)                                     \
-  ({                                                        \
-    __u64 ia64_intri_res;                                   \
-    asm ("popcnt %0=%1" : "=r" (ia64_intri_res) : "r" (x)); \
-    ia64_intri_res;                                         \
-  })
-#endif
-
-static __inline__ unsigned long
-grub_log2 (unsigned long word)
-{
-  unsigned long result;
-
-  result = ia64_popcnt((word - 1) & ~word);
-  return result;
-}
-
-#elif defined(__powerpc__)
-
-#ifdef __powerpc64__
-#define PPC_CNTLZL "cntlzd"
-#else
-#define PPC_CNTLZL "cntlzw"
-#endif
-#define BITS_PER_LONG (sizeof(long) * 8)
-
-static __inline__ int
-__ilog2(unsigned long x)
-{
-  int lz;
-
-  asm (PPC_CNTLZL " %0,%1" : "=r" (lz) : "r" (x));
-  return BITS_PER_LONG - 1 - lz;
-}
-
-static __inline__ unsigned long
-grub_log2 (unsigned long word)
-{
-  return __ilog2(word & -word);
-}
-
-#else /* Unoptimized */
-
-static __inline__ unsigned long
-grub_log2 (unsigned long word)
-{
-  unsigned long result = 0;
-
-  while (!(word & 1UL))
-    {
-      result++;
-      word >>= 1;
-    }
-  return result;
-}
-#endif
 #define log2 grub_log2
 
 static __inline__ int
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/include/xen_console.h
--- a/tools/libxen/include/xen_console.h        Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libxen/include/xen_console.h        Thu Feb 22 10:15:29 2007 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, XenSource Inc.
+ * Copyright (c) 2006-2007, XenSource Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -22,12 +22,13 @@
 #include "xen_common.h"
 #include "xen_console_decl.h"
 #include "xen_console_protocol.h"
+#include "xen_string_string_map.h"
 #include "xen_vm_decl.h"
 
 
 /*
- * The console class. 
- *  
+ * The console class.
+ * 
  * A console.
  */
 
@@ -65,8 +66,9 @@ typedef struct xen_console_record
     xen_console handle;
     char *uuid;
     enum xen_console_protocol protocol;
-    char *uri;
+    char *location;
     struct xen_vm_record_opt *vm;
+    xen_string_string_map *other_config;
 } xen_console_record;
 
 /**
@@ -191,10 +193,10 @@ xen_console_get_protocol(xen_session *se
 
 
 /**
- * Get the uri field of the given console.
- */
-extern bool
-xen_console_get_uri(xen_session *session, char **result, xen_console console);
+ * Get the location field of the given console.
+ */
+extern bool
+xen_console_get_location(xen_session *session, char **result, xen_console 
console);
 
 
 /**
@@ -204,4 +206,35 @@ xen_console_get_vm(xen_session *session,
 xen_console_get_vm(xen_session *session, xen_vm *result, xen_console console);
 
 
+/**
+ * Get the other_config field of the given console.
+ */
+extern bool
+xen_console_get_other_config(xen_session *session, xen_string_string_map 
**result, xen_console console);
+
+
+/**
+ * Set the other_config field of the given console.
+ */
+extern bool
+xen_console_set_other_config(xen_session *session, xen_console console, 
xen_string_string_map *other_config);
+
+
+/**
+ * Add the given key-value pair to the other_config field of the given
+ * console.
+ */
+extern bool
+xen_console_add_to_other_config(xen_session *session, xen_console console, 
char *key, char *value);
+
+
+/**
+ * Remove the given key and its corresponding value from the
+ * other_config field of the given console.  If the key is not in that Map,
+ * then do nothing.
+ */
+extern bool
+xen_console_remove_from_other_config(xen_session *session, xen_console 
console, char *key);
+
+
 #endif
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/include/xen_host.h
--- a/tools/libxen/include/xen_host.h   Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libxen/include/xen_host.h   Thu Feb 22 10:15:29 2007 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, XenSource Inc.
+ * Copyright (c) 2006-2007, XenSource Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -26,6 +26,7 @@
 #include "xen_pbd_decl.h"
 #include "xen_pif_decl.h"
 #include "xen_sr_decl.h"
+#include "xen_string_set.h"
 #include "xen_string_string_map.h"
 #include "xen_vm_decl.h"
 
@@ -73,6 +74,7 @@ typedef struct xen_host_record
     char *name_description;
     xen_string_string_map *software_version;
     xen_string_string_map *other_config;
+    struct xen_string_set *supported_bootloaders;
     struct xen_vm_record_opt_set *resident_vms;
     xen_string_string_map *logging;
     struct xen_pif_record_opt_set *pifs;
@@ -177,20 +179,6 @@ xen_host_get_by_uuid(xen_session *sessio
 
 
 /**
- * Create a new host instance, and return its handle.
- */
-extern bool
-xen_host_create(xen_session *session, xen_host *result, xen_host_record 
*record);
-
-
-/**
- * Destroy the specified host instance.
- */
-extern bool
-xen_host_destroy(xen_session *session, xen_host host);
-
-
-/**
  * Get all the host instances with the given label.
  */
 extern bool
@@ -230,6 +218,13 @@ xen_host_get_software_version(xen_sessio
  */
 extern bool
 xen_host_get_other_config(xen_session *session, xen_string_string_map 
**result, xen_host host);
+
+
+/**
+ * Get the supported_bootloaders field of the given host.
+ */
+extern bool
+xen_host_get_supported_bootloaders(xen_session *session, struct xen_string_set 
**result, xen_host host);
 
 
 /**
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/include/xen_internal.h
--- a/tools/libxen/include/xen_internal.h       Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libxen/include/xen_internal.h       Thu Feb 22 10:15:29 2007 -0700
@@ -149,7 +149,10 @@ type__ ## _set *                        
 type__ ## _set *                                                        \
 type__ ## _set_alloc(size_t size)                                       \
 {                                                                       \
-    return calloc(1, sizeof(type__ ## _set) + size * sizeof(type__));   \
+    type__ ## _set *result = calloc(1, sizeof(type__ ## _set) +         \
+                                    size * sizeof(type__));             \
+    result->size = size;                                                \
+    return result;                                                      \
 }                                                                       \
                                                                         \
 void                                                                    \
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/include/xen_string_set.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxen/include/xen_string_set.h     Thu Feb 22 10:15:29 2007 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2006-2007, XenSource Inc.
+ *
+ * This library 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+
+#ifndef XEN_STRING_SET_H
+#define XEN_STRING_SET_H
+
+
+#include "xen_common.h"
+
+
+typedef struct xen_string_set
+{
+    size_t size;
+    char *contents[];
+} xen_string_set;
+
+
+/**
+ * Allocate a xen_string_set of the given size.
+ */
+extern xen_string_set *
+xen_string_set_alloc(size_t size);
+
+/**
+ * Free the given xen_string_set.  The given set must have been allocated
+ * by this library.
+ */
+extern void
+xen_string_set_free(xen_string_set *set);
+
+
+#endif
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/include/xen_vbd.h
--- a/tools/libxen/include/xen_vbd.h    Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libxen/include/xen_vbd.h    Thu Feb 22 10:15:29 2007 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, XenSource Inc.
+ * Copyright (c) 2006-2007, XenSource Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -20,8 +20,11 @@
 #define XEN_VBD_H
 
 #include "xen_common.h"
+#include "xen_string_string_map.h"
 #include "xen_vbd_decl.h"
+#include "xen_vbd_metrics_decl.h"
 #include "xen_vbd_mode.h"
+#include "xen_vbd_type.h"
 #include "xen_vdi_decl.h"
 #include "xen_vm_decl.h"
 
@@ -71,8 +74,10 @@ typedef struct xen_vbd_record
     char *image;
     bool bootable;
     enum xen_vbd_mode mode;
-    double io_read_kbs;
-    double io_write_kbs;
+    enum xen_vbd_type type;
+    char *qos_algorithm_type;
+    xen_string_string_map *qos_algorithm_params;
+    struct xen_vbd_metrics_record_opt *metrics;
 } xen_vbd_record;
 
 /**
@@ -155,14 +160,14 @@ xen_vbd_record_opt_set_free(xen_vbd_reco
 
 
 /**
- * Get the current state of the given VBD.  !!!
+ * Get a record containing the current state of the given VBD.
  */
 extern bool
 xen_vbd_get_record(xen_session *session, xen_vbd_record **result, xen_vbd vbd);
 
 
 /**
- * Get a reference to the object with the specified UUID.  !!!
+ * Get a reference to the VBD instance with the specified UUID.
  */
 extern bool
 xen_vbd_get_by_uuid(xen_session *session, xen_vbd *result, char *uuid);
@@ -225,17 +230,31 @@ xen_vbd_get_mode(xen_session *session, e
 
 
 /**
- * Get the io/read_kbs field of the given VBD.
- */
-extern bool
-xen_vbd_get_io_read_kbs(xen_session *session, double *result, xen_vbd vbd);
-
-
-/**
- * Get the io/write_kbs field of the given VBD.
- */
-extern bool
-xen_vbd_get_io_write_kbs(xen_session *session, double *result, xen_vbd vbd);
+ * Get the type field of the given VBD.
+ */
+extern bool
+xen_vbd_get_type(xen_session *session, enum xen_vbd_type *result, xen_vbd vbd);
+
+
+/**
+ * Get the qos/algorithm_type field of the given VBD.
+ */
+extern bool
+xen_vbd_get_qos_algorithm_type(xen_session *session, char **result, xen_vbd 
vbd);
+
+
+/**
+ * Get the qos/algorithm_params field of the given VBD.
+ */
+extern bool
+xen_vbd_get_qos_algorithm_params(xen_session *session, xen_string_string_map 
**result, xen_vbd vbd);
+
+
+/**
+ * Get the metrics field of the given VBD.
+ */
+extern bool
+xen_vbd_get_metrics(xen_session *session, xen_vbd_metrics *result, xen_vbd 
vbd);
 
 
 /**
@@ -257,6 +276,44 @@ xen_vbd_set_bootable(xen_session *sessio
  */
 extern bool
 xen_vbd_set_mode(xen_session *session, xen_vbd vbd, enum xen_vbd_mode mode);
+
+
+/**
+ * Set the type field of the given VBD.
+ */
+extern bool
+xen_vbd_set_type(xen_session *session, xen_vbd vbd, enum xen_vbd_type type);
+
+
+/**
+ * Set the qos/algorithm_type field of the given VBD.
+ */
+extern bool
+xen_vbd_set_qos_algorithm_type(xen_session *session, xen_vbd vbd, char 
*algorithm_type);
+
+
+/**
+ * Set the qos/algorithm_params field of the given VBD.
+ */
+extern bool
+xen_vbd_set_qos_algorithm_params(xen_session *session, xen_vbd vbd, 
xen_string_string_map *algorithm_params);
+
+
+/**
+ * Add the given key-value pair to the qos/algorithm_params field of
+ * the given VBD.
+ */
+extern bool
+xen_vbd_add_to_qos_algorithm_params(xen_session *session, xen_vbd vbd, char 
*key, char *value);
+
+
+/**
+ * Remove the given key and its corresponding value from the
+ * qos/algorithm_params field of the given VBD.  If the key is not in that
+ * Map, then do nothing.
+ */
+extern bool
+xen_vbd_remove_from_qos_algorithm_params(xen_session *session, xen_vbd vbd, 
char *key);
 
 
 /**
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/include/xen_vbd_metrics.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxen/include/xen_vbd_metrics.h    Thu Feb 22 10:15:29 2007 -0700
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2006-2007, XenSource Inc.
+ *
+ * This library 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+
+#ifndef XEN_VBD_METRICS_H
+#define XEN_VBD_METRICS_H
+
+#include "xen_common.h"
+#include "xen_vbd_metrics_decl.h"
+
+
+/*
+ * The VBD_metrics class.
+ * 
+ * The metrics associated with a virtual block device.
+ */
+
+
+/**
+ * Free the given xen_vbd_metrics.  The given handle must have been
+ * allocated by this library.
+ */
+extern void
+xen_vbd_metrics_free(xen_vbd_metrics vbd_metrics);
+
+
+typedef struct xen_vbd_metrics_set
+{
+    size_t size;
+    xen_vbd_metrics *contents[];
+} xen_vbd_metrics_set;
+
+/**
+ * Allocate a xen_vbd_metrics_set of the given size.
+ */
+extern xen_vbd_metrics_set *
+xen_vbd_metrics_set_alloc(size_t size);
+
+/**
+ * Free the given xen_vbd_metrics_set.  The given set must have been
+ * allocated by this library.
+ */
+extern void
+xen_vbd_metrics_set_free(xen_vbd_metrics_set *set);
+
+
+typedef struct xen_vbd_metrics_record
+{
+    xen_vbd_metrics handle;
+    char *uuid;
+    double io_read_kbs;
+    double io_write_kbs;
+} xen_vbd_metrics_record;
+
+/**
+ * Allocate a xen_vbd_metrics_record.
+ */
+extern xen_vbd_metrics_record *
+xen_vbd_metrics_record_alloc(void);
+
+/**
+ * Free the given xen_vbd_metrics_record, and all referenced values. 
+ * The given record must have been allocated by this library.
+ */
+extern void
+xen_vbd_metrics_record_free(xen_vbd_metrics_record *record);
+
+
+typedef struct xen_vbd_metrics_record_opt
+{
+    bool is_record;
+    union
+    {
+        xen_vbd_metrics handle;
+        xen_vbd_metrics_record *record;
+    } u;
+} xen_vbd_metrics_record_opt;
+
+/**
+ * Allocate a xen_vbd_metrics_record_opt.
+ */
+extern xen_vbd_metrics_record_opt *
+xen_vbd_metrics_record_opt_alloc(void);
+
+/**
+ * Free the given xen_vbd_metrics_record_opt, and all referenced
+ * values.  The given record_opt must have been allocated by this library.
+ */
+extern void
+xen_vbd_metrics_record_opt_free(xen_vbd_metrics_record_opt *record_opt);
+
+
+typedef struct xen_vbd_metrics_record_set
+{
+    size_t size;
+    xen_vbd_metrics_record *contents[];
+} xen_vbd_metrics_record_set;
+
+/**
+ * Allocate a xen_vbd_metrics_record_set of the given size.
+ */
+extern xen_vbd_metrics_record_set *
+xen_vbd_metrics_record_set_alloc(size_t size);
+
+/**
+ * Free the given xen_vbd_metrics_record_set, and all referenced
+ * values.  The given set must have been allocated by this library.
+ */
+extern void
+xen_vbd_metrics_record_set_free(xen_vbd_metrics_record_set *set);
+
+
+
+typedef struct xen_vbd_metrics_record_opt_set
+{
+    size_t size;
+    xen_vbd_metrics_record_opt *contents[];
+} xen_vbd_metrics_record_opt_set;
+
+/**
+ * Allocate a xen_vbd_metrics_record_opt_set of the given size.
+ */
+extern xen_vbd_metrics_record_opt_set *
+xen_vbd_metrics_record_opt_set_alloc(size_t size);
+
+/**
+ * Free the given xen_vbd_metrics_record_opt_set, and all referenced
+ * values.  The given set must have been allocated by this library.
+ */
+extern void
+xen_vbd_metrics_record_opt_set_free(xen_vbd_metrics_record_opt_set *set);
+
+
+/**
+ * Get a record containing the current state of the given VBD_metrics.
+ */
+extern bool
+xen_vbd_metrics_get_record(xen_session *session, xen_vbd_metrics_record 
**result, xen_vbd_metrics vbd_metrics);
+
+
+/**
+ * Get a reference to the VBD_metrics instance with the specified UUID.
+ */
+extern bool
+xen_vbd_metrics_get_by_uuid(xen_session *session, xen_vbd_metrics *result, 
char *uuid);
+
+
+/**
+ * Get the uuid field of the given VBD_metrics.
+ */
+extern bool
+xen_vbd_metrics_get_uuid(xen_session *session, char **result, xen_vbd_metrics 
vbd_metrics);
+
+
+/**
+ * Get the io/read_kbs field of the given VBD_metrics.
+ */
+extern bool
+xen_vbd_metrics_get_io_read_kbs(xen_session *session, double *result, 
xen_vbd_metrics vbd_metrics);
+
+
+/**
+ * Get the io/write_kbs field of the given VBD_metrics.
+ */
+extern bool
+xen_vbd_metrics_get_io_write_kbs(xen_session *session, double *result, 
xen_vbd_metrics vbd_metrics);
+
+
+#endif
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/include/xen_vbd_metrics_decl.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxen/include/xen_vbd_metrics_decl.h       Thu Feb 22 10:15:29 
2007 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2006-2007, XenSource Inc.
+ *
+ * This library 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+
+#ifndef XEN_VBD_METRICS_DECL_H
+#define XEN_VBD_METRICS_DECL_H
+
+typedef void *xen_vbd_metrics;
+
+struct xen_vbd_metrics_set;
+struct xen_vbd_metrics_record;
+struct xen_vbd_metrics_record_set;
+struct xen_vbd_metrics_record_opt;
+struct xen_vbd_metrics_record_opt_set;
+
+#endif
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/include/xen_vbd_type.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxen/include/xen_vbd_type.h       Thu Feb 22 10:15:29 2007 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2006-2007, XenSource Inc.
+ *
+ * This library 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+
+#ifndef XEN_VBD_TYPE_H
+#define XEN_VBD_TYPE_H
+
+
+#include "xen_common.h"
+
+
+enum xen_vbd_type
+{
+    /**
+     * VBD will appear to guest as CD
+     */
+    XEN_VBD_TYPE_CD,
+
+    /**
+     * VBD will appear to guest as disk
+     */
+    XEN_VBD_TYPE_DISK
+};
+
+
+typedef struct xen_vbd_type_set
+{
+    size_t size;
+    enum xen_vbd_type contents[];
+} xen_vbd_type_set;
+
+/**
+ * Allocate a xen_vbd_type_set of the given size.
+ */
+extern xen_vbd_type_set *
+xen_vbd_type_set_alloc(size_t size);
+
+/**
+ * Free the given xen_vbd_type_set.  The given set must have been
+ * allocated by this library.
+ */
+extern void
+xen_vbd_type_set_free(xen_vbd_type_set *set);
+
+
+/**
+ * Return the name corresponding to the given code.  This string must
+ * not be modified or freed.
+ */
+extern const char *
+xen_vbd_type_to_string(enum xen_vbd_type val);
+
+
+/**
+ * Return the correct code for the given string, or set the session
+ * object to failure and return an undefined value if the given string does
+ * not match a known code.
+ */
+extern enum xen_vbd_type
+xen_vbd_type_from_string(xen_session *session, const char *str);
+
+
+#endif
diff -r 9364bea18bc4 -r 202eb735b425 
tools/libxen/include/xen_vbd_type_internal.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxen/include/xen_vbd_type_internal.h      Thu Feb 22 10:15:29 
2007 -0700
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2006-2007, XenSource Inc.
+ *
+ * This library 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+
+
+/*
+ * Declarations of the abstract types used during demarshalling of enum
+ * xen_vbd_type.  Internal to this library -- do not use from outside.
+ */
+
+
+#ifndef XEN_VBD_TYPE_INTERNAL_H
+#define XEN_VBD_TYPE_INTERNAL_H
+
+
+#include "xen_internal.h"
+
+
+extern const abstract_type xen_vbd_type_abstract_type_;
+extern const abstract_type xen_vbd_type_set_abstract_type_;
+
+
+#endif
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/include/xen_vif.h
--- a/tools/libxen/include/xen_vif.h    Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libxen/include/xen_vif.h    Thu Feb 22 10:15:29 2007 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, XenSource Inc.
+ * Copyright (c) 2006-2007, XenSource Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -21,7 +21,9 @@
 
 #include "xen_common.h"
 #include "xen_network_decl.h"
+#include "xen_string_string_map.h"
 #include "xen_vif_decl.h"
+#include "xen_vif_metrics_decl.h"
 #include "xen_vm_decl.h"
 
 
@@ -69,8 +71,9 @@ typedef struct xen_vif_record
     struct xen_vm_record_opt *vm;
     char *mac;
     int64_t mtu;
-    double io_read_kbs;
-    double io_write_kbs;
+    char *qos_algorithm_type;
+    xen_string_string_map *qos_algorithm_params;
+    struct xen_vif_metrics_record_opt *metrics;
 } xen_vif_record;
 
 /**
@@ -223,17 +226,24 @@ xen_vif_get_mtu(xen_session *session, in
 
 
 /**
- * Get the io/read_kbs field of the given VIF.
- */
-extern bool
-xen_vif_get_io_read_kbs(xen_session *session, double *result, xen_vif vif);
-
-
-/**
- * Get the io/write_kbs field of the given VIF.
- */
-extern bool
-xen_vif_get_io_write_kbs(xen_session *session, double *result, xen_vif vif);
+ * Get the qos/algorithm_type field of the given VIF.
+ */
+extern bool
+xen_vif_get_qos_algorithm_type(xen_session *session, char **result, xen_vif 
vif);
+
+
+/**
+ * Get the qos/algorithm_params field of the given VIF.
+ */
+extern bool
+xen_vif_get_qos_algorithm_params(xen_session *session, xen_string_string_map 
**result, xen_vif vif);
+
+
+/**
+ * Get the metrics field of the given VIF.
+ */
+extern bool
+xen_vif_get_metrics(xen_session *session, xen_vif_metrics *result, xen_vif 
vif);
 
 
 /**
@@ -257,4 +267,35 @@ xen_vif_set_mtu(xen_session *session, xe
 xen_vif_set_mtu(xen_session *session, xen_vif vif, int64_t mtu);
 
 
+/**
+ * Set the qos/algorithm_type field of the given VIF.
+ */
+extern bool
+xen_vif_set_qos_algorithm_type(xen_session *session, xen_vif vif, char 
*algorithm_type);
+
+
+/**
+ * Set the qos/algorithm_params field of the given VIF.
+ */
+extern bool
+xen_vif_set_qos_algorithm_params(xen_session *session, xen_vif vif, 
xen_string_string_map *algorithm_params);
+
+
+/**
+ * Add the given key-value pair to the qos/algorithm_params field of
+ * the given VIF.
+ */
+extern bool
+xen_vif_add_to_qos_algorithm_params(xen_session *session, xen_vif vif, char 
*key, char *value);
+
+
+/**
+ * Remove the given key and its corresponding value from the
+ * qos/algorithm_params field of the given VIF.  If the key is not in that
+ * Map, then do nothing.
+ */
+extern bool
+xen_vif_remove_from_qos_algorithm_params(xen_session *session, xen_vif vif, 
char *key);
+
+
 #endif
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/include/xen_vif_metrics.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxen/include/xen_vif_metrics.h    Thu Feb 22 10:15:29 2007 -0700
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2006-2007, XenSource Inc.
+ *
+ * This library 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+
+#ifndef XEN_VIF_METRICS_H
+#define XEN_VIF_METRICS_H
+
+#include "xen_common.h"
+#include "xen_vif_metrics_decl.h"
+
+
+/*
+ * The VIF_metrics class.
+ * 
+ * The metrics associated with a virtual network device.
+ */
+
+
+/**
+ * Free the given xen_vif_metrics.  The given handle must have been
+ * allocated by this library.
+ */
+extern void
+xen_vif_metrics_free(xen_vif_metrics vif_metrics);
+
+
+typedef struct xen_vif_metrics_set
+{
+    size_t size;
+    xen_vif_metrics *contents[];
+} xen_vif_metrics_set;
+
+/**
+ * Allocate a xen_vif_metrics_set of the given size.
+ */
+extern xen_vif_metrics_set *
+xen_vif_metrics_set_alloc(size_t size);
+
+/**
+ * Free the given xen_vif_metrics_set.  The given set must have been
+ * allocated by this library.
+ */
+extern void
+xen_vif_metrics_set_free(xen_vif_metrics_set *set);
+
+
+typedef struct xen_vif_metrics_record
+{
+    xen_vif_metrics handle;
+    char *uuid;
+    double io_read_kbs;
+    double io_write_kbs;
+} xen_vif_metrics_record;
+
+/**
+ * Allocate a xen_vif_metrics_record.
+ */
+extern xen_vif_metrics_record *
+xen_vif_metrics_record_alloc(void);
+
+/**
+ * Free the given xen_vif_metrics_record, and all referenced values. 
+ * The given record must have been allocated by this library.
+ */
+extern void
+xen_vif_metrics_record_free(xen_vif_metrics_record *record);
+
+
+typedef struct xen_vif_metrics_record_opt
+{
+    bool is_record;
+    union
+    {
+        xen_vif_metrics handle;
+        xen_vif_metrics_record *record;
+    } u;
+} xen_vif_metrics_record_opt;
+
+/**
+ * Allocate a xen_vif_metrics_record_opt.
+ */
+extern xen_vif_metrics_record_opt *
+xen_vif_metrics_record_opt_alloc(void);
+
+/**
+ * Free the given xen_vif_metrics_record_opt, and all referenced
+ * values.  The given record_opt must have been allocated by this library.
+ */
+extern void
+xen_vif_metrics_record_opt_free(xen_vif_metrics_record_opt *record_opt);
+
+
+typedef struct xen_vif_metrics_record_set
+{
+    size_t size;
+    xen_vif_metrics_record *contents[];
+} xen_vif_metrics_record_set;
+
+/**
+ * Allocate a xen_vif_metrics_record_set of the given size.
+ */
+extern xen_vif_metrics_record_set *
+xen_vif_metrics_record_set_alloc(size_t size);
+
+/**
+ * Free the given xen_vif_metrics_record_set, and all referenced
+ * values.  The given set must have been allocated by this library.
+ */
+extern void
+xen_vif_metrics_record_set_free(xen_vif_metrics_record_set *set);
+
+
+
+typedef struct xen_vif_metrics_record_opt_set
+{
+    size_t size;
+    xen_vif_metrics_record_opt *contents[];
+} xen_vif_metrics_record_opt_set;
+
+/**
+ * Allocate a xen_vif_metrics_record_opt_set of the given size.
+ */
+extern xen_vif_metrics_record_opt_set *
+xen_vif_metrics_record_opt_set_alloc(size_t size);
+
+/**
+ * Free the given xen_vif_metrics_record_opt_set, and all referenced
+ * values.  The given set must have been allocated by this library.
+ */
+extern void
+xen_vif_metrics_record_opt_set_free(xen_vif_metrics_record_opt_set *set);
+
+
+/**
+ * Get a record containing the current state of the given VIF_metrics.
+ */
+extern bool
+xen_vif_metrics_get_record(xen_session *session, xen_vif_metrics_record 
**result, xen_vif_metrics vif_metrics);
+
+
+/**
+ * Get a reference to the VIF_metrics instance with the specified UUID.
+ */
+extern bool
+xen_vif_metrics_get_by_uuid(xen_session *session, xen_vif_metrics *result, 
char *uuid);
+
+
+/**
+ * Get the uuid field of the given VIF_metrics.
+ */
+extern bool
+xen_vif_metrics_get_uuid(xen_session *session, char **result, xen_vif_metrics 
vif_metrics);
+
+
+/**
+ * Get the io/read_kbs field of the given VIF_metrics.
+ */
+extern bool
+xen_vif_metrics_get_io_read_kbs(xen_session *session, double *result, 
xen_vif_metrics vif_metrics);
+
+
+/**
+ * Get the io/write_kbs field of the given VIF_metrics.
+ */
+extern bool
+xen_vif_metrics_get_io_write_kbs(xen_session *session, double *result, 
xen_vif_metrics vif_metrics);
+
+
+#endif
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/include/xen_vif_metrics_decl.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxen/include/xen_vif_metrics_decl.h       Thu Feb 22 10:15:29 
2007 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2006-2007, XenSource Inc.
+ *
+ * This library 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+
+#ifndef XEN_VIF_METRICS_DECL_H
+#define XEN_VIF_METRICS_DECL_H
+
+typedef void *xen_vif_metrics;
+
+struct xen_vif_metrics_set;
+struct xen_vif_metrics_record;
+struct xen_vif_metrics_record_set;
+struct xen_vif_metrics_record_opt;
+struct xen_vif_metrics_record_opt_set;
+
+#endif
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/include/xen_vm_metrics.h
--- a/tools/libxen/include/xen_vm_metrics.h     Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libxen/include/xen_vm_metrics.h     Thu Feb 22 10:15:29 2007 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, XenSource Inc.
+ * Copyright (c) 2006-2007, XenSource Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -21,7 +21,6 @@
 
 #include "xen_common.h"
 #include "xen_int_float_map.h"
-#include "xen_vm_decl.h"
 #include "xen_vm_metrics_decl.h"
 
 
@@ -64,7 +63,6 @@ typedef struct xen_vm_metrics_record
 {
     xen_vm_metrics handle;
     char *uuid;
-    struct xen_vm_record_opt *vm;
     int64_t memory_actual;
     int64_t vcpus_number;
     xen_int_float_map *vcpus_utilisation;
@@ -171,13 +169,6 @@ xen_vm_metrics_get_uuid(xen_session *ses
 
 
 /**
- * Get the VM field of the given VM_metrics.
- */
-extern bool
-xen_vm_metrics_get_vm(xen_session *session, xen_vm *result, xen_vm_metrics 
vm_metrics);
-
-
-/**
  * Get the memory/actual field of the given VM_metrics.
  */
 extern bool
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/src/xen_common.c
--- a/tools/libxen/src/xen_common.c     Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libxen/src/xen_common.c     Thu Feb 22 10:15:29 2007 -0700
@@ -989,10 +989,10 @@ static void parse_failure(xen_session *s
         char **c = (char **)error_descriptions->contents;
         int n = error_descriptions->size;
 
-        char **strings = malloc(3 * sizeof(char *));
+        char **strings = malloc(n * sizeof(char *));
         for (int i = 0; i < n; i++)
         {
-            strings[i] = xen_strdup_(c[i]);
+            strings[i] = c[i];
         }
 
         session->error_description_count = n;
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/src/xen_console.c
--- a/tools/libxen/src/xen_console.c    Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libxen/src/xen_console.c    Thu Feb 22 10:15:29 2007 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, XenSource Inc.
+ * Copyright (c) 2006-2007, XenSource Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -24,6 +24,7 @@
 #include "xen_console.h"
 #include "xen_console_protocol_internal.h"
 #include "xen_internal.h"
+#include "xen_string_string_map.h"
 #include "xen_vm.h"
 
 
@@ -44,12 +45,15 @@ static const struct_member xen_console_r
         { .key = "protocol",
           .type = &xen_console_protocol_abstract_type_,
           .offset = offsetof(xen_console_record, protocol) },
-        { .key = "uri",
+        { .key = "location",
           .type = &abstract_type_string,
-          .offset = offsetof(xen_console_record, uri) },
+          .offset = offsetof(xen_console_record, location) },
         { .key = "VM",
           .type = &abstract_type_ref,
-          .offset = offsetof(xen_console_record, vm) }
+          .offset = offsetof(xen_console_record, vm) },
+        { .key = "other_config",
+          .type = &abstract_type_string_string_map,
+          .offset = offsetof(xen_console_record, other_config) }
     };
 
 const abstract_type xen_console_record_abstract_type_ =
@@ -71,8 +75,9 @@ xen_console_record_free(xen_console_reco
     }
     free(record->handle);
     free(record->uuid);
-    free(record->uri);
+    free(record->location);
     xen_vm_record_opt_free(record->vm);
+    xen_string_string_map_free(record->other_config);
     free(record);
 }
 
@@ -164,18 +169,18 @@ xen_console_get_protocol(xen_session *se
 
 
 bool
-xen_console_get_uri(xen_session *session, char **result, xen_console console)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = console }
-        };
-
-    abstract_type result_type = abstract_type_string;
-
-    *result = NULL;
-    XEN_CALL_("console.get_uri");
+xen_console_get_location(xen_session *session, char **result, xen_console 
console)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = console }
+        };
+
+    abstract_type result_type = abstract_type_string;
+
+    *result = NULL;
+    XEN_CALL_("console.get_location");
     return session->ok;
 }
 
@@ -198,6 +203,73 @@ xen_console_get_vm(xen_session *session,
 
 
 bool
+xen_console_get_other_config(xen_session *session, xen_string_string_map 
**result, xen_console console)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = console }
+        };
+
+    abstract_type result_type = abstract_type_string_string_map;
+
+    *result = NULL;
+    XEN_CALL_("console.get_other_config");
+    return session->ok;
+}
+
+
+bool
+xen_console_set_other_config(xen_session *session, xen_console console, 
xen_string_string_map *other_config)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = console },
+            { .type = &abstract_type_string_string_map,
+              .u.set_val = (arbitrary_set *)other_config }
+        };
+
+    xen_call_(session, "console.set_other_config", param_values, 2, NULL, 
NULL);
+    return session->ok;
+}
+
+
+bool
+xen_console_add_to_other_config(xen_session *session, xen_console console, 
char *key, char *value)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = console },
+            { .type = &abstract_type_string,
+              .u.string_val = key },
+            { .type = &abstract_type_string,
+              .u.string_val = value }
+        };
+
+    xen_call_(session, "console.add_to_other_config", param_values, 3, NULL, 
NULL);
+    return session->ok;
+}
+
+
+bool
+xen_console_remove_from_other_config(xen_session *session, xen_console 
console, char *key)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = console },
+            { .type = &abstract_type_string,
+              .u.string_val = key }
+        };
+
+    xen_call_(session, "console.remove_from_other_config", param_values, 2, 
NULL, NULL);
+    return session->ok;
+}
+
+
+bool
 xen_console_get_uuid(xen_session *session, char **result, xen_console console)
 {
     *result = session->ok ? xen_strdup_((char *)console) : NULL;
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/src/xen_host.c
--- a/tools/libxen/src/xen_host.c       Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libxen/src/xen_host.c       Thu Feb 22 10:15:29 2007 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, XenSource Inc.
+ * Copyright (c) 2006-2007, XenSource Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -58,6 +58,9 @@ static const struct_member xen_host_reco
         { .key = "other_config",
           .type = &abstract_type_string_string_map,
           .offset = offsetof(xen_host_record, other_config) },
+        { .key = "supported_bootloaders",
+          .type = &abstract_type_string_set,
+          .offset = offsetof(xen_host_record, supported_bootloaders) },
         { .key = "resident_VMs",
           .type = &abstract_type_ref_set,
           .offset = offsetof(xen_host_record, resident_vms) },
@@ -107,6 +110,7 @@ xen_host_record_free(xen_host_record *re
     free(record->name_description);
     xen_string_string_map_free(record->software_version);
     xen_string_string_map_free(record->other_config);
+    xen_string_set_free(record->supported_bootloaders);
     xen_vm_record_opt_set_free(record->resident_vms);
     xen_string_string_map_free(record->logging);
     xen_pif_record_opt_set_free(record->pifs);
@@ -160,37 +164,6 @@ xen_host_get_by_uuid(xen_session *sessio
 
 
 bool
-xen_host_create(xen_session *session, xen_host *result, xen_host_record 
*record)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &xen_host_record_abstract_type_,
-              .u.struct_val = record }
-        };
-
-    abstract_type result_type = abstract_type_string;
-
-    *result = NULL;
-    XEN_CALL_("host.create");
-    return session->ok;
-}
-
-
-bool
-xen_host_destroy(xen_session *session, xen_host host)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = host }
-        };
-
-    xen_call_(session, "host.destroy", param_values, 1, NULL, NULL);
-    return session->ok;
-}
-
-
-bool
 xen_host_get_by_name_label(xen_session *session, struct xen_host_set **result, 
char *label)
 {
     abstract_value param_values[] =
@@ -271,6 +244,23 @@ xen_host_get_other_config(xen_session *s
 
     *result = NULL;
     XEN_CALL_("host.get_other_config");
+    return session->ok;
+}
+
+
+bool
+xen_host_get_supported_bootloaders(xen_session *session, struct xen_string_set 
**result, xen_host host)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = host }
+        };
+
+    abstract_type result_type = abstract_type_string_set;
+
+    *result = NULL;
+    XEN_CALL_("host.get_supported_bootloaders");
     return session->ok;
 }
 
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/src/xen_string_set.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxen/src/xen_string_set.c Thu Feb 22 10:15:29 2007 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2006-2007, XenSource Inc.
+ *
+ * This library 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+
+
+#include "xen_internal.h"
+#include "xen_string_set.h"
+
+
+xen_string_set *
+xen_string_set_alloc(size_t size)
+{
+    xen_string_set *result = calloc(1, sizeof(xen_string_set) +
+                                    size * sizeof(char *));
+    result->size = size;
+    return result;
+}
+
+void
+xen_string_set_free(xen_string_set *set)
+{
+    if (set == NULL)
+    {
+        return;
+    }
+    size_t n = set->size;
+    for (size_t i = 0; i < n; i++)
+    {
+       free(set->contents[i]);
+    }
+
+    free(set);
+}
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/src/xen_string_set.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxen/src/xen_string_set.h Thu Feb 22 10:15:29 2007 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2006-2007, XenSource Inc.
+ *
+ * This library 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+
+#ifndef XEN_STRING_SET_H
+#define XEN_STRING_SET_H
+
+
+#include "xen_common.h"
+
+
+typedef struct xen_string_set
+{
+    size_t size;
+    char *contents[];
+} xen_string_set;
+
+
+/**
+ * Allocate a xen_string_set of the given size.
+ */
+extern xen_string_set *
+xen_string_set_alloc(size_t size);
+
+/**
+ * Free the given xen_string_set.  The given set must have been allocated
+ * by this library.
+ */
+extern void
+xen_string_set_free(xen_string_set *set);
+
+
+#endif
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/src/xen_vbd.c
--- a/tools/libxen/src/xen_vbd.c        Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libxen/src/xen_vbd.c        Thu Feb 22 10:15:29 2007 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, XenSource Inc.
+ * Copyright (c) 2006-2007, XenSource Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -22,8 +22,11 @@
 
 #include "xen_common.h"
 #include "xen_internal.h"
+#include "xen_string_string_map.h"
 #include "xen_vbd.h"
+#include "xen_vbd_metrics.h"
 #include "xen_vbd_mode_internal.h"
+#include "xen_vbd_type_internal.h"
 #include "xen_vdi.h"
 #include "xen_vm.h"
 
@@ -60,12 +63,18 @@ static const struct_member xen_vbd_recor
         { .key = "mode",
           .type = &xen_vbd_mode_abstract_type_,
           .offset = offsetof(xen_vbd_record, mode) },
-        { .key = "io_read_kbs",
-          .type = &abstract_type_float,
-          .offset = offsetof(xen_vbd_record, io_read_kbs) },
-        { .key = "io_write_kbs",
-          .type = &abstract_type_float,
-          .offset = offsetof(xen_vbd_record, io_write_kbs) }
+        { .key = "type",
+          .type = &xen_vbd_type_abstract_type_,
+          .offset = offsetof(xen_vbd_record, type) },
+        { .key = "qos_algorithm_type",
+          .type = &abstract_type_string,
+          .offset = offsetof(xen_vbd_record, qos_algorithm_type) },
+        { .key = "qos_algorithm_params",
+          .type = &abstract_type_string_string_map,
+          .offset = offsetof(xen_vbd_record, qos_algorithm_params) },
+        { .key = "metrics",
+          .type = &abstract_type_ref,
+          .offset = offsetof(xen_vbd_record, metrics) }
     };
 
 const abstract_type xen_vbd_record_abstract_type_ =
@@ -90,6 +99,9 @@ xen_vbd_record_free(xen_vbd_record *reco
     xen_vm_record_opt_free(record->vm);
     xen_vdi_record_opt_free(record->vdi);
     free(record->device);
+    free(record->qos_algorithm_type);
+    xen_string_string_map_free(record->qos_algorithm_params);
+    xen_vbd_metrics_record_opt_free(record->metrics);
     free(record);
 }
 
@@ -242,41 +254,73 @@ xen_vbd_get_mode(xen_session *session, e
         };
 
     abstract_type result_type = xen_vbd_mode_abstract_type_;
-    char *result_str = NULL;
     XEN_CALL_("VBD.get_mode");
-    *result = xen_vbd_mode_from_string(session, result_str);
-    return session->ok;
-}
-
-
-bool
-xen_vbd_get_io_read_kbs(xen_session *session, double *result, xen_vbd vbd)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = vbd }
-        };
-
-    abstract_type result_type = abstract_type_float;
-
-    XEN_CALL_("VBD.get_io_read_kbs");
-    return session->ok;
-}
-
-
-bool
-xen_vbd_get_io_write_kbs(xen_session *session, double *result, xen_vbd vbd)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = vbd }
-        };
-
-    abstract_type result_type = abstract_type_float;
-
-    XEN_CALL_("VBD.get_io_write_kbs");
+    return session->ok;
+}
+
+
+bool
+xen_vbd_get_type(xen_session *session, enum xen_vbd_type *result, xen_vbd vbd)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vbd }
+        };
+
+    abstract_type result_type = xen_vbd_type_abstract_type_;
+    XEN_CALL_("VBD.get_type");
+    return session->ok;
+}
+
+
+bool
+xen_vbd_get_qos_algorithm_type(xen_session *session, char **result, xen_vbd 
vbd)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vbd }
+        };
+
+    abstract_type result_type = abstract_type_string;
+
+    *result = NULL;
+    XEN_CALL_("VBD.get_qos_algorithm_type");
+    return session->ok;
+}
+
+
+bool
+xen_vbd_get_qos_algorithm_params(xen_session *session, xen_string_string_map 
**result, xen_vbd vbd)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vbd }
+        };
+
+    abstract_type result_type = abstract_type_string_string_map;
+
+    *result = NULL;
+    XEN_CALL_("VBD.get_qos_algorithm_params");
+    return session->ok;
+}
+
+
+bool
+xen_vbd_get_metrics(xen_session *session, xen_vbd_metrics *result, xen_vbd vbd)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vbd }
+        };
+
+    abstract_type result_type = abstract_type_string;
+
+    *result = NULL;
+    XEN_CALL_("VBD.get_metrics");
     return session->ok;
 }
 
@@ -330,6 +374,88 @@ xen_vbd_set_mode(xen_session *session, x
 
 
 bool
+xen_vbd_set_type(xen_session *session, xen_vbd vbd, enum xen_vbd_type type)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vbd },
+            { .type = &xen_vbd_type_abstract_type_,
+              .u.string_val = xen_vbd_type_to_string(type) }
+        };
+
+    xen_call_(session, "VBD.set_type", param_values, 2, NULL, NULL);
+    return session->ok;
+}
+
+
+bool
+xen_vbd_set_qos_algorithm_type(xen_session *session, xen_vbd vbd, char 
*algorithm_type)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vbd },
+            { .type = &abstract_type_string,
+              .u.string_val = algorithm_type }
+        };
+
+    xen_call_(session, "VBD.set_qos_algorithm_type", param_values, 2, NULL, 
NULL);
+    return session->ok;
+}
+
+
+bool
+xen_vbd_set_qos_algorithm_params(xen_session *session, xen_vbd vbd, 
xen_string_string_map *algorithm_params)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vbd },
+            { .type = &abstract_type_string_string_map,
+              .u.set_val = (arbitrary_set *)algorithm_params }
+        };
+
+    xen_call_(session, "VBD.set_qos_algorithm_params", param_values, 2, NULL, 
NULL);
+    return session->ok;
+}
+
+
+bool
+xen_vbd_add_to_qos_algorithm_params(xen_session *session, xen_vbd vbd, char 
*key, char *value)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vbd },
+            { .type = &abstract_type_string,
+              .u.string_val = key },
+            { .type = &abstract_type_string,
+              .u.string_val = value }
+        };
+
+    xen_call_(session, "VBD.add_to_qos_algorithm_params", param_values, 3, 
NULL, NULL);
+    return session->ok;
+}
+
+
+bool
+xen_vbd_remove_from_qos_algorithm_params(xen_session *session, xen_vbd vbd, 
char *key)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vbd },
+            { .type = &abstract_type_string,
+              .u.string_val = key }
+        };
+
+    xen_call_(session, "VBD.remove_from_qos_algorithm_params", param_values, 
2, NULL, NULL);
+    return session->ok;
+}
+
+
+bool
 xen_vbd_media_change(xen_session *session, xen_vbd vbd, xen_vdi vdi)
 {
     abstract_value param_values[] =
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/src/xen_vbd_metrics.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxen/src/xen_vbd_metrics.c        Thu Feb 22 10:15:29 2007 -0700
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2006-2007, XenSource Inc.
+ *
+ * This library 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "xen_common.h"
+#include "xen_internal.h"
+#include "xen_vbd_metrics.h"
+
+
+XEN_FREE(xen_vbd_metrics)
+XEN_SET_ALLOC_FREE(xen_vbd_metrics)
+XEN_ALLOC(xen_vbd_metrics_record)
+XEN_SET_ALLOC_FREE(xen_vbd_metrics_record)
+XEN_ALLOC(xen_vbd_metrics_record_opt)
+XEN_RECORD_OPT_FREE(xen_vbd_metrics)
+XEN_SET_ALLOC_FREE(xen_vbd_metrics_record_opt)
+
+
+static const struct_member xen_vbd_metrics_record_struct_members[] =
+    {
+        { .key = "uuid",
+          .type = &abstract_type_string,
+          .offset = offsetof(xen_vbd_metrics_record, uuid) },
+        { .key = "io_read_kbs",
+          .type = &abstract_type_float,
+          .offset = offsetof(xen_vbd_metrics_record, io_read_kbs) },
+        { .key = "io_write_kbs",
+          .type = &abstract_type_float,
+          .offset = offsetof(xen_vbd_metrics_record, io_write_kbs) }
+    };
+
+const abstract_type xen_vbd_metrics_record_abstract_type_ =
+    {
+       .typename = STRUCT,
+       .struct_size = sizeof(xen_vbd_metrics_record),
+       .member_count =
+           sizeof(xen_vbd_metrics_record_struct_members) / 
sizeof(struct_member),
+       .members = xen_vbd_metrics_record_struct_members
+    };
+
+
+void
+xen_vbd_metrics_record_free(xen_vbd_metrics_record *record)
+{
+    if (record == NULL)
+    {
+        return;
+    }
+    free(record->handle);
+    free(record->uuid);
+    free(record);
+}
+
+
+bool
+xen_vbd_metrics_get_record(xen_session *session, xen_vbd_metrics_record 
**result, xen_vbd_metrics vbd_metrics)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vbd_metrics }
+        };
+
+    abstract_type result_type = xen_vbd_metrics_record_abstract_type_;
+
+    *result = NULL;
+    XEN_CALL_("VBD_metrics.get_record");
+
+    if (session->ok)
+    {
+       (*result)->handle = xen_strdup_((*result)->uuid);
+    }
+
+    return session->ok;
+}
+
+
+bool
+xen_vbd_metrics_get_by_uuid(xen_session *session, xen_vbd_metrics *result, 
char *uuid)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = uuid }
+        };
+
+    abstract_type result_type = abstract_type_string;
+
+    *result = NULL;
+    XEN_CALL_("VBD_metrics.get_by_uuid");
+    return session->ok;
+}
+
+
+bool
+xen_vbd_metrics_get_io_read_kbs(xen_session *session, double *result, 
xen_vbd_metrics vbd_metrics)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vbd_metrics }
+        };
+
+    abstract_type result_type = abstract_type_float;
+
+    XEN_CALL_("VBD_metrics.get_io_read_kbs");
+    return session->ok;
+}
+
+
+bool
+xen_vbd_metrics_get_io_write_kbs(xen_session *session, double *result, 
xen_vbd_metrics vbd_metrics)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vbd_metrics }
+        };
+
+    abstract_type result_type = abstract_type_float;
+
+    XEN_CALL_("VBD_metrics.get_io_write_kbs");
+    return session->ok;
+}
+
+
+bool
+xen_vbd_metrics_get_uuid(xen_session *session, char **result, xen_vbd_metrics 
vbd_metrics)
+{
+    *result = session->ok ? xen_strdup_((char *)vbd_metrics) : NULL;
+    return session->ok;
+}
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/src/xen_vbd_type.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxen/src/xen_vbd_type.c   Thu Feb 22 10:15:29 2007 -0700
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2006-2007, XenSource Inc.
+ *
+ * This library 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+
+#include <string.h>
+
+#include "xen_internal.h"
+#include "xen_vbd_type.h"
+#include "xen_vbd_type_internal.h"
+
+
+/*
+ * Maintain this in the same order as the enum declaration!
+ */
+static const char *lookup_table[] =
+{
+    "CD",
+    "Disk"
+};
+
+
+extern xen_vbd_type_set *
+xen_vbd_type_set_alloc(size_t size)
+{
+    return calloc(1, sizeof(xen_vbd_type_set) +
+                  size * sizeof(enum xen_vbd_type));
+}
+
+
+extern void
+xen_vbd_type_set_free(xen_vbd_type_set *set)
+{
+    free(set);
+}
+
+
+const char *
+xen_vbd_type_to_string(enum xen_vbd_type val)
+{
+    return lookup_table[val];
+}
+
+
+extern enum xen_vbd_type
+xen_vbd_type_from_string(xen_session *session, const char *str)
+{
+    return ENUM_LOOKUP(session, str, lookup_table);
+}
+
+
+const abstract_type xen_vbd_type_abstract_type_ =
+    {
+        .typename = ENUM,
+        .enum_marshaller =
+             (const char *(*)(int))&xen_vbd_type_to_string,
+        .enum_demarshaller =
+             (int (*)(xen_session *, const char *))&xen_vbd_type_from_string
+    };
+
+
+const abstract_type xen_vbd_type_set_abstract_type_ =
+    {
+        .typename = SET,
+        .child = &xen_vbd_type_abstract_type_
+    };
+
+
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/src/xen_vif.c
--- a/tools/libxen/src/xen_vif.c        Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libxen/src/xen_vif.c        Thu Feb 22 10:15:29 2007 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, XenSource Inc.
+ * Copyright (c) 2006-2007, XenSource Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -23,7 +23,9 @@
 #include "xen_common.h"
 #include "xen_internal.h"
 #include "xen_network.h"
+#include "xen_string_string_map.h"
 #include "xen_vif.h"
+#include "xen_vif_metrics.h"
 #include "xen_vm.h"
 
 
@@ -56,12 +58,15 @@ static const struct_member xen_vif_recor
         { .key = "MTU",
           .type = &abstract_type_int,
           .offset = offsetof(xen_vif_record, mtu) },
-        { .key = "io_read_kbs",
-          .type = &abstract_type_float,
-          .offset = offsetof(xen_vif_record, io_read_kbs) },
-        { .key = "io_write_kbs",
-          .type = &abstract_type_float,
-          .offset = offsetof(xen_vif_record, io_write_kbs) }
+        { .key = "qos_algorithm_type",
+          .type = &abstract_type_string,
+          .offset = offsetof(xen_vif_record, qos_algorithm_type) },
+        { .key = "qos_algorithm_params",
+          .type = &abstract_type_string_string_map,
+          .offset = offsetof(xen_vif_record, qos_algorithm_params) },
+        { .key = "metrics",
+          .type = &abstract_type_ref,
+          .offset = offsetof(xen_vif_record, metrics) }
     };
 
 const abstract_type xen_vif_record_abstract_type_ =
@@ -87,6 +92,9 @@ xen_vif_record_free(xen_vif_record *reco
     xen_network_record_opt_free(record->network);
     xen_vm_record_opt_free(record->vm);
     free(record->mac);
+    free(record->qos_algorithm_type);
+    xen_string_string_map_free(record->qos_algorithm_params);
+    xen_vif_metrics_record_opt_free(record->metrics);
     free(record);
 }
 
@@ -247,33 +255,52 @@ xen_vif_get_mtu(xen_session *session, in
 
 
 bool
-xen_vif_get_io_read_kbs(xen_session *session, double *result, xen_vif vif)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = vif }
-        };
-
-    abstract_type result_type = abstract_type_float;
-
-    XEN_CALL_("VIF.get_io_read_kbs");
-    return session->ok;
-}
-
-
-bool
-xen_vif_get_io_write_kbs(xen_session *session, double *result, xen_vif vif)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = vif }
-        };
-
-    abstract_type result_type = abstract_type_float;
-
-    XEN_CALL_("VIF.get_io_write_kbs");
+xen_vif_get_qos_algorithm_type(xen_session *session, char **result, xen_vif 
vif)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vif }
+        };
+
+    abstract_type result_type = abstract_type_string;
+
+    *result = NULL;
+    XEN_CALL_("VIF.get_qos_algorithm_type");
+    return session->ok;
+}
+
+
+bool
+xen_vif_get_qos_algorithm_params(xen_session *session, xen_string_string_map 
**result, xen_vif vif)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vif }
+        };
+
+    abstract_type result_type = abstract_type_string_string_map;
+
+    *result = NULL;
+    XEN_CALL_("VIF.get_qos_algorithm_params");
+    return session->ok;
+}
+
+
+bool
+xen_vif_get_metrics(xen_session *session, xen_vif_metrics *result, xen_vif vif)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vif }
+        };
+
+    abstract_type result_type = abstract_type_string;
+
+    *result = NULL;
+    XEN_CALL_("VIF.get_metrics");
     return session->ok;
 }
 
@@ -327,6 +354,72 @@ xen_vif_set_mtu(xen_session *session, xe
 
 
 bool
+xen_vif_set_qos_algorithm_type(xen_session *session, xen_vif vif, char 
*algorithm_type)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vif },
+            { .type = &abstract_type_string,
+              .u.string_val = algorithm_type }
+        };
+
+    xen_call_(session, "VIF.set_qos_algorithm_type", param_values, 2, NULL, 
NULL);
+    return session->ok;
+}
+
+
+bool
+xen_vif_set_qos_algorithm_params(xen_session *session, xen_vif vif, 
xen_string_string_map *algorithm_params)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vif },
+            { .type = &abstract_type_string_string_map,
+              .u.set_val = (arbitrary_set *)algorithm_params }
+        };
+
+    xen_call_(session, "VIF.set_qos_algorithm_params", param_values, 2, NULL, 
NULL);
+    return session->ok;
+}
+
+
+bool
+xen_vif_add_to_qos_algorithm_params(xen_session *session, xen_vif vif, char 
*key, char *value)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vif },
+            { .type = &abstract_type_string,
+              .u.string_val = key },
+            { .type = &abstract_type_string,
+              .u.string_val = value }
+        };
+
+    xen_call_(session, "VIF.add_to_qos_algorithm_params", param_values, 3, 
NULL, NULL);
+    return session->ok;
+}
+
+
+bool
+xen_vif_remove_from_qos_algorithm_params(xen_session *session, xen_vif vif, 
char *key)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vif },
+            { .type = &abstract_type_string,
+              .u.string_val = key }
+        };
+
+    xen_call_(session, "VIF.remove_from_qos_algorithm_params", param_values, 
2, NULL, NULL);
+    return session->ok;
+}
+
+
+bool
 xen_vif_get_uuid(xen_session *session, char **result, xen_vif vif)
 {
     *result = session->ok ? xen_strdup_((char *)vif) : NULL;
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/src/xen_vif_metrics.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxen/src/xen_vif_metrics.c        Thu Feb 22 10:15:29 2007 -0700
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2006-2007, XenSource Inc.
+ *
+ * This library 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; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "xen_common.h"
+#include "xen_internal.h"
+#include "xen_vif_metrics.h"
+
+
+XEN_FREE(xen_vif_metrics)
+XEN_SET_ALLOC_FREE(xen_vif_metrics)
+XEN_ALLOC(xen_vif_metrics_record)
+XEN_SET_ALLOC_FREE(xen_vif_metrics_record)
+XEN_ALLOC(xen_vif_metrics_record_opt)
+XEN_RECORD_OPT_FREE(xen_vif_metrics)
+XEN_SET_ALLOC_FREE(xen_vif_metrics_record_opt)
+
+
+static const struct_member xen_vif_metrics_record_struct_members[] =
+    {
+        { .key = "uuid",
+          .type = &abstract_type_string,
+          .offset = offsetof(xen_vif_metrics_record, uuid) },
+        { .key = "io_read_kbs",
+          .type = &abstract_type_float,
+          .offset = offsetof(xen_vif_metrics_record, io_read_kbs) },
+        { .key = "io_write_kbs",
+          .type = &abstract_type_float,
+          .offset = offsetof(xen_vif_metrics_record, io_write_kbs) }
+    };
+
+const abstract_type xen_vif_metrics_record_abstract_type_ =
+    {
+       .typename = STRUCT,
+       .struct_size = sizeof(xen_vif_metrics_record),
+       .member_count =
+           sizeof(xen_vif_metrics_record_struct_members) / 
sizeof(struct_member),
+       .members = xen_vif_metrics_record_struct_members
+    };
+
+
+void
+xen_vif_metrics_record_free(xen_vif_metrics_record *record)
+{
+    if (record == NULL)
+    {
+        return;
+    }
+    free(record->handle);
+    free(record->uuid);
+    free(record);
+}
+
+
+bool
+xen_vif_metrics_get_record(xen_session *session, xen_vif_metrics_record 
**result, xen_vif_metrics vif_metrics)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vif_metrics }
+        };
+
+    abstract_type result_type = xen_vif_metrics_record_abstract_type_;
+
+    *result = NULL;
+    XEN_CALL_("VIF_metrics.get_record");
+
+    if (session->ok)
+    {
+       (*result)->handle = xen_strdup_((*result)->uuid);
+    }
+
+    return session->ok;
+}
+
+
+bool
+xen_vif_metrics_get_by_uuid(xen_session *session, xen_vif_metrics *result, 
char *uuid)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = uuid }
+        };
+
+    abstract_type result_type = abstract_type_string;
+
+    *result = NULL;
+    XEN_CALL_("VIF_metrics.get_by_uuid");
+    return session->ok;
+}
+
+
+bool
+xen_vif_metrics_get_io_read_kbs(xen_session *session, double *result, 
xen_vif_metrics vif_metrics)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vif_metrics }
+        };
+
+    abstract_type result_type = abstract_type_float;
+
+    XEN_CALL_("VIF_metrics.get_io_read_kbs");
+    return session->ok;
+}
+
+
+bool
+xen_vif_metrics_get_io_write_kbs(xen_session *session, double *result, 
xen_vif_metrics vif_metrics)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vif_metrics }
+        };
+
+    abstract_type result_type = abstract_type_float;
+
+    XEN_CALL_("VIF_metrics.get_io_write_kbs");
+    return session->ok;
+}
+
+
+bool
+xen_vif_metrics_get_uuid(xen_session *session, char **result, xen_vif_metrics 
vif_metrics)
+{
+    *result = session->ok ? xen_strdup_((char *)vif_metrics) : NULL;
+    return session->ok;
+}
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/src/xen_vm_metrics.c
--- a/tools/libxen/src/xen_vm_metrics.c Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libxen/src/xen_vm_metrics.c Thu Feb 22 10:15:29 2007 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, XenSource Inc.
+ * Copyright (c) 2006-2007, XenSource Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -23,7 +23,6 @@
 #include "xen_common.h"
 #include "xen_int_float_map.h"
 #include "xen_internal.h"
-#include "xen_vm.h"
 #include "xen_vm_metrics.h"
 
 
@@ -41,9 +40,6 @@ static const struct_member xen_vm_metric
         { .key = "uuid",
           .type = &abstract_type_string,
           .offset = offsetof(xen_vm_metrics_record, uuid) },
-        { .key = "VM",
-          .type = &abstract_type_ref,
-          .offset = offsetof(xen_vm_metrics_record, vm) },
         { .key = "memory_actual",
           .type = &abstract_type_int,
           .offset = offsetof(xen_vm_metrics_record, memory_actual) },
@@ -74,7 +70,6 @@ xen_vm_metrics_record_free(xen_vm_metric
     }
     free(record->handle);
     free(record->uuid);
-    xen_vm_record_opt_free(record->vm);
     xen_int_float_map_free(record->vcpus_utilisation);
     free(record);
 }
@@ -121,23 +116,6 @@ xen_vm_metrics_get_by_uuid(xen_session *
 
 
 bool
-xen_vm_metrics_get_vm(xen_session *session, xen_vm *result, xen_vm_metrics 
vm_metrics)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = vm_metrics }
-        };
-
-    abstract_type result_type = abstract_type_string;
-
-    *result = NULL;
-    XEN_CALL_("VM_metrics.get_VM");
-    return session->ok;
-}
-
-
-bool
 xen_vm_metrics_get_memory_actual(xen_session *session, int64_t *result, 
xen_vm_metrics vm_metrics)
 {
     abstract_value param_values[] =
diff -r 9364bea18bc4 -r 202eb735b425 tools/libxen/test/test_bindings.c
--- a/tools/libxen/test/test_bindings.c Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/libxen/test/test_bindings.c Thu Feb 22 10:15:29 2007 -0700
@@ -31,6 +31,7 @@
 #include "xen_vdi.h"
 #include "xen_console.h"
 #include "xen_vm.h"
+#include "xen_vm_metrics.h"
 
 
 static void usage()
@@ -61,6 +62,7 @@ typedef struct
 
 static xen_vm create_new_vm(xen_session *session, bool hvm);
 static void print_vm_power_state(xen_session *session, xen_vm vm);
+static void print_vm_metrics(xen_session *session, xen_vm vm);
 
 
 static size_t
@@ -220,6 +222,22 @@ int main(int argc, char **argv)
         return 1;
     }
 
+    xen_string_set *supported_bootloaders;
+    if (!xen_host_get_supported_bootloaders(session, &supported_bootloaders,
+                                            host))
+    {
+        print_error(session);
+        free(dmesg);
+        xen_string_string_map_free(versions);
+        xen_host_free(host);
+        xen_vm_record_free(vm_record);
+        xen_uuid_bytes_free(vm_uuid_bytes);
+        xen_uuid_free(vm_uuid);
+        xen_vm_free(vm);
+        CLEANUP;
+        return 1;
+    }
+
     printf("%s.\n", vm_uuid);
 
     fprintf(stderr, "In bytes, the VM UUID is ");
@@ -239,29 +257,39 @@ int main(int argc, char **argv)
 
     printf("Host dmesg follows:\n%s\n\n", dmesg);
 
+    printf("Host supports the following bootloaders:");
+    for (size_t i = 0; i < supported_bootloaders->size; i++)
+    {
+        printf(" %s", supported_bootloaders->contents[i]);
+    }
+    printf("\n");
+
     printf("%s.\n", vm_record->uuid);
 
     printf("Resident on %s.\n", (char *)vm_record->resident_on->u.handle);
 
     printf("%s.\n", xen_vm_power_state_to_string(vm_record->power_state));
-
-    for (size_t i = 0; i < vm_record->vcpus_utilisation->size; i++)
-    {
-        printf("%"PRId64" -> %lf.\n",
-               vm_record->vcpus_utilisation->contents[i].key,
-               vm_record->vcpus_utilisation->contents[i].val);
-    }
 
     xen_uuid_bytes_free(vm_uuid_bytes);
     xen_uuid_free(vm_uuid);
-    xen_vm_free(vm);
 
     xen_vm_record_free(vm_record);
 
     xen_host_free(host);
     xen_string_string_map_free(versions);
     free(dmesg);
-
+    xen_string_set_free(supported_bootloaders);
+
+    print_vm_metrics(session, vm);
+    if (!session->ok)
+    {
+        /* Error has been logged, just clean up. */
+        xen_vm_free(vm);
+        CLEANUP;
+        return 1;
+    }
+
+    xen_vm_free(vm);
 
     xen_vm new_vm = create_new_vm(session, true);
     if (!session->ok)
@@ -323,7 +351,6 @@ static xen_vm create_new_vm(xen_session 
             .memory_static_min = 128,
             .vcpus_policy = "credit",
             .vcpus_params = vcpus_params,
-            .vcpus_number = 2,
             .actions_after_shutdown = XEN_ON_NORMAL_EXIT_DESTROY,
             .actions_after_reboot = XEN_ON_NORMAL_EXIT_RESTART,
             .actions_after_crash = XEN_ON_CRASH_BEHAVIOUR_PRESERVE,
@@ -519,3 +546,35 @@ static void print_vm_power_state(xen_ses
 
     xen_uuid_free(vm_uuid);
 }
+
+
+/**
+ * Print the metrics for the given VM.
+ */
+static void print_vm_metrics(xen_session *session, xen_vm vm)
+{
+    xen_vm_metrics vm_metrics;
+    if (!xen_vm_get_metrics(session, &vm_metrics, vm))
+    {
+        print_error(session);
+        return;
+    }
+
+    xen_vm_metrics_record *vm_metrics_record;
+    if (!xen_vm_metrics_get_record(session, &vm_metrics_record, vm_metrics))
+    {
+        xen_vm_metrics_free(vm_metrics);
+        print_error(session);
+        return;
+    }
+
+    for (size_t i = 0; i < vm_metrics_record->vcpus_utilisation->size; i++)
+    {
+        printf("%"PRId64" -> %lf.\n",
+               vm_metrics_record->vcpus_utilisation->contents[i].key,
+               vm_metrics_record->vcpus_utilisation->contents[i].val);
+    }
+
+    xen_vm_metrics_record_free(vm_metrics_record);
+    xen_vm_metrics_free(vm_metrics);
+}
diff -r 9364bea18bc4 -r 202eb735b425 tools/python/xen/xend/XendAPI.py
--- a/tools/python/xen/xend/XendAPI.py  Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/python/xen/xend/XendAPI.py  Thu Feb 22 10:15:29 2007 -0700
@@ -141,11 +141,11 @@ def _is_valid_ref(ref, validator):
 def _is_valid_ref(ref, validator):
     return type(ref) == str and validator(ref)
 
-def _check_ref(validator, errcode, func, api, session, ref, *args, **kwargs):
+def _check_ref(validator, clas, func, api, session, ref, *args, **kwargs):
     if _is_valid_ref(ref, validator):
         return func(api, session, ref, *args, **kwargs)
     else:
-        return xen_api_error([errcode, ref])
+        return xen_api_error(['HANDLE_INVALID', clas, ref])
 
 
 def valid_host(func):
@@ -156,7 +156,7 @@ def valid_host(func):
     """
     return lambda *args, **kwargs: \
            _check_ref(XendNode.instance().is_valid_host,
-                      'HOST_HANDLE_INVALID', func, *args, **kwargs)
+                      'host', func, *args, **kwargs)
 
 def valid_host_metrics(func):
     """Decorator to verify if host_metrics_ref is valid before calling
@@ -167,7 +167,7 @@ def valid_host_metrics(func):
     """
     return lambda *args, **kwargs: \
            _check_ref(lambda r: r == XendNode.instance().host_metrics_uuid,
-                      'HOST_METRICS_HANDLE_INVALID', func, *args, **kwargs)
+                      'host_metrics', func, *args, **kwargs)
 
 def valid_host_cpu(func):
     """Decorator to verify if host_cpu_ref is valid before calling method.
@@ -177,7 +177,7 @@ def valid_host_cpu(func):
     """    
     return lambda *args, **kwargs: \
            _check_ref(XendNode.instance().is_valid_cpu,
-                      'HOST_CPU_HANDLE_INVALID', func, *args, **kwargs)
+                      'host_cpu', func, *args, **kwargs)
 
 def valid_vm(func):
     """Decorator to verify if vm_ref is valid before calling method.
@@ -187,7 +187,7 @@ def valid_vm(func):
     """    
     return lambda *args, **kwargs: \
            _check_ref(XendDomain.instance().is_valid_vm,
-                      'VM_HANDLE_INVALID', func, *args, **kwargs)
+                      'VM', func, *args, **kwargs)
 
 def valid_network(func):
     """Decorator to verify if network_ref is valid before calling method.
@@ -197,7 +197,7 @@ def valid_network(func):
     """    
     return lambda *args, **kwargs: \
            _check_ref(XendNode.instance().is_valid_network,
-                      'NETWORK_HANDLE_INVALID', func, *args, **kwargs)
+                      'network', func, *args, **kwargs)
 
 def valid_vbd(func):
     """Decorator to verify if vbd_ref is valid before calling method.
@@ -207,7 +207,17 @@ def valid_vbd(func):
     """    
     return lambda *args, **kwargs: \
            _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
-                      'VBD_HANDLE_INVALID', func, *args, **kwargs)
+                      'VBD', func, *args, **kwargs)
+
+def valid_vbd_metrics(func):
+    """Decorator to verify if ref is valid before calling method.
+
+    @param func: function with params: (self, session, ref, ...)
+    @rtype: callable object
+    """    
+    return lambda *args, **kwargs: \
+           _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r),
+                      'VBD_metrics', func, *args, **kwargs)
 
 def valid_vif(func):
     """Decorator to verify if vif_ref is valid before calling method.
@@ -217,7 +227,17 @@ def valid_vif(func):
     """
     return lambda *args, **kwargs: \
            _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
-                      'VIF_HANDLE_INVALID', func, *args, **kwargs)
+                      'VIF', func, *args, **kwargs)
+
+def valid_vif_metrics(func):
+    """Decorator to verify if ref is valid before calling method.
+
+    @param func: function with params: (self, session, ref, ...)
+    @rtype: callable object
+    """    
+    return lambda *args, **kwargs: \
+           _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r),
+                      'VIF_metrics', func, *args, **kwargs)
 
 def valid_vdi(func):
     """Decorator to verify if vdi_ref is valid before calling method.
@@ -227,7 +247,7 @@ def valid_vdi(func):
     """
     return lambda *args, **kwargs: \
            _check_ref(XendNode.instance().is_valid_vdi,
-                      'VDI_HANDLE_INVALID', func, *args, **kwargs)
+                      'VDI', func, *args, **kwargs)
 
 def valid_vtpm(func):
     """Decorator to verify if vtpm_ref is valid before calling method.
@@ -237,7 +257,7 @@ def valid_vtpm(func):
     """
     return lambda *args, **kwargs: \
            _check_ref(lambda r: XendDomain.instance().is_valid_dev('vtpm', r),
-                      'VTPM_HANDLE_INVALID', func, *args, **kwargs)
+                      'VTPM', func, *args, **kwargs)
 
 
 def valid_console(func):
@@ -249,7 +269,7 @@ def valid_console(func):
     return lambda *args, **kwargs: \
            _check_ref(lambda r: XendDomain.instance().is_valid_dev('console',
                                                                    r),
-                      'CONSOLE_HANDLE_INVALID', func, *args, **kwargs)
+                      'console', func, *args, **kwargs)
 
 def valid_sr(func):
     """Decorator to verify if sr_ref is valid before calling method.
@@ -259,7 +279,7 @@ def valid_sr(func):
     """
     return lambda *args, **kwargs: \
            _check_ref(lambda r: XendNode.instance().is_valid_sr,
-                      'SR_HANDLE_INVALID', func, *args, **kwargs)
+                      'SR', func, *args, **kwargs)
 
 def valid_pif(func):
     """Decorator to verify if pif_ref is valid before calling
@@ -270,7 +290,7 @@ def valid_pif(func):
     """
     return lambda *args, **kwargs: \
            _check_ref(lambda r: r in XendNode.instance().pifs,
-                      'PIF_HANDLE_INVALID', func, *args, **kwargs)
+                      'PIF', func, *args, **kwargs)
 
 def valid_pif_metrics(func):
     """Decorator to verify if pif_metrics_ref is valid before calling
@@ -281,7 +301,7 @@ def valid_pif_metrics(func):
     """
     return lambda *args, **kwargs: \
            _check_ref(lambda r: r in XendNode.instance().pif_metrics,
-                      'PIF_METRICS_HANDLE_INVALID', func, *args, **kwargs)
+                      'PIF_metrics', func, *args, **kwargs)
 
 def valid_task(func):
     """Decorator to verify if task_ref is valid before calling
@@ -292,7 +312,7 @@ def valid_task(func):
     """
     return lambda *args, **kwargs: \
            _check_ref(XendTaskManager.get_task,
-                      'TASK_HANDLE_INVALID', func, *args, **kwargs)
+                      'task', func, *args, **kwargs)
 
 def valid_debug(func):
     """Decorator to verify if task_ref is valid before calling
@@ -303,7 +323,7 @@ def valid_debug(func):
     """
     return lambda *args, **kwargs: \
            _check_ref(lambda r: r in XendAPI._debug,
-                      'TASK_HANDLE_INVALID', func, *args, **kwargs)
+                      'debug', func, *args, **kwargs)
 
 # -----------------------------
 # Bridge to Legacy XM API calls
@@ -378,7 +398,9 @@ class XendAPI(object):
             'network'      : valid_network,
             'VM'           : valid_vm,
             'VBD'          : valid_vbd,
+            'VBD_metrics'  : valid_vbd_metrics,
             'VIF'          : valid_vif,
+            'VIF_metrics'  : valid_vif_metrics,
             'VDI'          : valid_vdi,
             'VTPM'         : valid_vtpm,
             'console'      : valid_console,
@@ -604,7 +626,8 @@ class XendAPI(object):
     host_attr_ro = ['software_version',
                     'resident_VMs',
                     'host_CPUs',
-                    'metrics']
+                    'metrics',
+                    'supported_bootloaders']
     
     host_attr_rw = ['name_label',
                     'name_description',
@@ -656,10 +679,10 @@ class XendAPI(object):
         return xen_api_success(XendNode.instance().get_host_cpu_refs())
     def host_get_metrics(self, _, ref):
         return xen_api_success(XendNode.instance().host_metrics_uuid)
+    def host_get_supported_bootloaders(self, session, host_ref):
+        return xen_api_success(['pygrub'])
 
     # object methods
-    def host_destroy(self, session, host_ref):
-        return xen_api_error(XEND_ERROR_UNSUPPORTED)    
     def host_disable(self, session, host_ref):
         XendDomain.instance().set_allow_new_domains(False)
         return xen_api_success_void()
@@ -687,14 +710,13 @@ class XendAPI(object):
                   'software_version': node.xen_version(),
                   'resident_VMs': dom.get_domain_refs(),
                   'host_CPUs': node.get_host_cpu_refs(),
-                  'metrics': node.host_metrics_uuid}
+                  'metrics': node.host_metrics_uuid,
+                  'supported_bootloaders': 'pygrub'}
         return xen_api_success(record)
 
     # class methods
     def host_get_all(self, session):
         return xen_api_success((XendNode.instance().uuid,))
-    def host_create(self, session, struct):
-        return xen_api_error(XEND_ERROR_UNSUPPORTED)
     def host_get_by_name_label(self, session, name):
         if XendNode.instance().name == name:
             return xen_api_success((XendNode.instance().uuid,))
@@ -908,7 +930,7 @@ class XendAPI(object):
                 return xen_api_success(
                     node.PIF_create_VLAN(ref, network, vlan))
             else:
-                return xen_api_error(['NETWORK_HANDLE_INVALID', network])
+                return xen_api_error(['HANDLE_INVALID', 'network', network])
         except NetworkAlreadyConnected, exn:
             return xen_api_error(['NETWORK_ALREADY_CONNECTED',
                                   network, exn.pif_uuid])
@@ -1352,7 +1374,7 @@ class XendAPI(object):
         xendom = XendDomain.instance()
         xeninfo = xendom.get_vm_by_uuid(vm_ref)
         if not xeninfo:
-            return xen_api_error(['VM_HANDLE_INVALID', vm_ref])
+            return xen_api_error(['HANDLE_INVALID', 'VM', vm_ref])
         
         record = {
             'uuid': xeninfo.get_uuid(),
@@ -1450,8 +1472,7 @@ class XendAPI(object):
     # Xen API: Class VBD
     # ----------------------------------------------------------------
 
-    VBD_attr_ro = ['io_read_kbs',
-                   'io_write_kbs']
+    VBD_attr_ro = ['metrics']
     VBD_attr_rw = ['VM',
                    'VDI',
                    'device',
@@ -1469,10 +1490,10 @@ class XendAPI(object):
         xendom = XendDomain.instance()
         vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
         if not vm:
-            return xen_api_error(['VBD_HANDLE_INVALID', vbd_ref])
+            return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
         cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
         if not cfg:
-            return xen_api_error(['VBD_HANDLE_INVALID', vbd_ref])
+            return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
 
         valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \
                          self.Base_attr_ro + self.Base_attr_rw
@@ -1481,7 +1502,9 @@ class XendAPI(object):
         for k in cfg.keys():
             if k in valid_vbd_keys:
                 return_cfg[k] = cfg[k]
-                
+
+        return_cfg['metrics'] = vbd_ref
+
         return xen_api_success(return_cfg)
 
     def VBD_media_change(self, session, vbd_ref, vdi_ref):
@@ -1491,7 +1514,7 @@ class XendAPI(object):
     def VBD_create(self, session, vbd_struct):
         xendom = XendDomain.instance()
         if not xendom.is_valid_vm(vbd_struct['VM']):
-            return xen_api_error(['VM_HANDLE_INVALID', vbd_struct['VM']])
+            return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
         
         dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
         vbd_ref = ''
@@ -1500,7 +1523,7 @@ class XendAPI(object):
             vdi_ref = vbd_struct.get('VDI')
             vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
             if not vdi:
-                return xen_api_error(['VDI_HANDLE_INVALID', vdi_ref])
+                return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
             vdi_image = vdi.get_location()
             vbd_ref = XendTask.log_progress(0, 100,
                                             dom.create_vbd,
@@ -1516,17 +1539,21 @@ class XendAPI(object):
         xendom = XendDomain.instance()
         vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
         if not vm:
-            return xen_api_error(['VBD_HANDLE_INVALID', vbd_ref])
+            return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
 
         XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
         return xen_api_success_void()
 
-    # attributes (rw)
     def _VBD_get(self, vbd_ref, prop):
         return xen_api_success(
             XendDomain.instance().get_dev_property_by_uuid(
             'vbd', vbd_ref, prop))
 
+    # attributes (ro)
+    def VBD_get_metrics(self, _, vbd_ref):
+        return xen_api_success(vbd_ref)
+
+    # attributes (rw)
     def VBD_get_VM(self, session, vbd_ref):
         return self._VBD_get(vbd_ref, 'VM')
     
@@ -1544,12 +1571,6 @@ class XendAPI(object):
 
     def VBD_get_type(self, session, vbd_ref):
         return self._VBD_get(vbd_ref, 'type')
-
-    def VBD_get_io_read_kbs(self, session, vbd_ref):
-        return self._VBD_get(vbd_ref, 'io_read_kbs')
-    
-    def VBD_get_io_write_kbs(self, session, vbd_ref):
-        return self._VBD_get(vbd_ref, 'io_write_kbs')
 
     def VBD_set_bootable(self, session, vbd_ref, bootable):
         bootable = bool(bootable)
@@ -1565,11 +1586,34 @@ class XendAPI(object):
         vbds = reduce(lambda x, y: x + y, vbds)
         return xen_api_success(vbds)
 
+
+    # Xen API: Class VBD_metrics
+    # ----------------------------------------------------------------
+
+    VBD_metrics_attr_ro = ['io_read_kbs',
+                           'io_write_kbs']
+    VBD_metrics_attr_rw = []
+    VBD_methods = []
+
+    def VBD_metrics_get_record(self, _, ref):
+        vm = XendDomain.instance().get_vm_with_dev_uuid('vbd', ref)
+        if not vm:
+            return xen_api_error(['HANDLE_INVALID', 'VBD_metrics', ref])
+        return xen_api_success(
+            { 'io_read_kbs'  : vm.get_dev_property('vbd', ref, 'io_read_kbs'),
+              'io_write_kbs' : vm.get_dev_property('vbd', ref, 'io_write_kbs') 
})
+
+    def VBD_metrics_get_io_read_kbs(self, _, ref):
+        return self._VBD_get(ref, 'io_read_kbs')
+    
+    def VBD_metrics_get_io_write_kbs(self, session, ref):
+        return self._VBD_get(ref, 'io_write_kbs')
+
+
     # Xen API: Class VIF
     # ----------------------------------------------------------------
 
-    VIF_attr_ro = ['io_read_kbs',
-                   'io_write_kbs']
+    VIF_attr_ro = ['metrics']
     VIF_attr_rw = ['device',
                    'network',
                    'VM',
@@ -1586,10 +1630,10 @@ class XendAPI(object):
         xendom = XendDomain.instance()
         vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
         if not vm:
-            return xen_api_error(['VIF_HANDLE_INVALID', vif_ref])
+            return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
         cfg = vm.get_dev_xenapi_config('vif', vif_ref)
         if not cfg:
-            return xen_api_error(['VIF_HANDLE_INVALID', vif_ref])
+            return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
         
         valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
                          self.Base_attr_ro + self.Base_attr_rw
@@ -1599,6 +1643,8 @@ class XendAPI(object):
             if k in valid_vif_keys:
                 return_cfg[k] = cfg[k]
             
+        return_cfg['metrics'] = vif_ref
+
         return xen_api_success(return_cfg)
 
     # class methods
@@ -1613,48 +1659,40 @@ class XendAPI(object):
             except XendError:
                 return xen_api_error(XEND_ERROR_TODO)
         else:
-            return xen_api_error(['VM_HANDLE_INVALID', vif_struct['VM']])
+            return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']])
 
 
     def VIF_destroy(self, session, vif_ref):
         xendom = XendDomain.instance()
         vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
         if not vm:
-            return xen_api_error(['VIF_HANDLE_INVALID', vif_ref])
+            return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref])
 
         vm.destroy_vif(vif_ref)
         return xen_api_success_void()
 
+    def _VIF_get(self, ref, prop):
+        return xen_api_success(
+            XendDomain.instance().get_dev_property_by_uuid('vif', ref, prop))
+
     # getters/setters
+    def VIF_get_metrics(self, _, vif_ref):
+        return xen_api_success(vif_ref)
+
     def VIF_get_VM(self, session, vif_ref):
         xendom = XendDomain.instance()        
         vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)        
         return xen_api_success(vm.get_uuid())
     
     def VIF_get_MTU(self, session, vif_ref):
-        xendom = XendDomain.instance()
-        return xen_api_success(xendom.get_dev_property_by_uuid('vif', vif_ref,
-                                                               'MTU'))
+        return self._VIF_get(vif_ref, 'MTU')
+    
     def VIF_get_MAC(self, session, vif_ref):
-        xendom = XendDomain.instance()
-        return xen_api_success(xendom.get_dev_property_by_uuid('vif', vif_ref,
-                                                               'MAC'))
+        return self._VIF_get(vif_ref, 'MAC')
 
     def VIF_get_device(self, session, vif_ref):
-        xendom = XendDomain.instance()
-        return xen_api_success(xendom.get_dev_property_by_uuid('vif', vif_ref,
-                                                               'device'))
+        return self._VIF_get(vif_ref, 'device')
  
-    def VIF_get_io_read_kbs(self, session, vif_ref):
-        xendom = XendDomain.instance()
-        return xen_api_success(xendom.get_dev_property_by_uuid('vif', vif_ref,
-                                                               'io_read_kbs'))
-
-    def VIF_get_io_write_kbs(self, session, vif_ref):
-        xendom = XendDomain.instance()
-        return xen_api_success(xendom.get_dev_property_by_uuid('vif', vif_ref,
-                                                               'io_write_kbs'))
-
     def VIF_get_all(self, session):
         xendom = XendDomain.instance()
         vifs = [d.get_vifs() for d in XendDomain.instance().list('all')]
@@ -1662,6 +1700,29 @@ class XendAPI(object):
         return xen_api_success(vifs)
 
     
+    # Xen API: Class VIF_metrics
+    # ----------------------------------------------------------------
+
+    VIF_metrics_attr_ro = ['io_read_kbs',
+                           'io_write_kbs']
+    VIF_metrics_attr_rw = []
+    VIF_methods = []
+
+    def VIF_metrics_get_record(self, _, ref):
+        vm = XendDomain.instance().get_vm_with_dev_uuid('vif', ref)
+        if not vm:
+            return xen_api_error(['HANDLE_INVALID', 'VIF_metrics', ref])
+        return xen_api_success(
+            { 'io_read_kbs'  : vm.get_dev_property('vif', ref, 'io_read_kbs'),
+              'io_write_kbs' : vm.get_dev_property('vif', ref, 'io_write_kbs') 
})
+
+    def VIF_metrics_get_io_read_kbs(self, _, ref):
+        return self._VIF_get(ref, 'io_read_kbs')
+    
+    def VIF_metrics_get_io_write_kbs(self, session, ref):
+        return self._VIF_get(ref, 'io_write_kbs')
+
+
     # Xen API: Class VDI
     # ----------------------------------------------------------------
     VDI_attr_ro = ['VBDs',
@@ -1766,7 +1827,7 @@ class XendAPI(object):
         sr_ref = vdi_struct.get('SR')
         xennode = XendNode.instance()
         if not xennode.is_valid_sr(sr_ref):
-            return xen_api_error(['SR_HANDLE_INVALID', sr_ref])
+            return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
 
         vdi_uuid = xennode.srs[sr_ref].create_vdi(vdi_struct)
         return xen_api_success(vdi_uuid)
@@ -1797,10 +1858,10 @@ class XendAPI(object):
         xendom = XendDomain.instance()
         vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
         if not vm:
-            return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
+            return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
         cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
         if not cfg:
-            return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
+            return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
         valid_vtpm_keys = self.VTPM_attr_ro + self.VTPM_attr_rw + \
                           self.Base_attr_ro + self.Base_attr_rw
         return_cfg = {}
@@ -1815,10 +1876,10 @@ class XendAPI(object):
         xendom = XendDomain.instance()
         vm = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
         if not vm:
-            return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
+            return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
         cfg = vm.get_dev_xenapi_config('vtpm', vtpm_ref)
         if not cfg:
-            return xen_api_error(['VTPM_HANDLE_INVALID', vtpm_ref])
+            return xen_api_error(['HANDLE_INVALID', 'VTPM', vtpm_ref])
         if not cfg.has_key('backend'):
             return xen_api_error(['VTPM backend not set'])
         return xen_api_success(cfg['backend'])
@@ -1841,7 +1902,7 @@ class XendAPI(object):
             tpmif.destroy_vtpmstate(dom.getName())
             return xen_api_success(True)
         else:
-            return xen_api_error(['VM_HANDLE_INVALID', vtpm_struct['VM']])
+            return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
 
     # class methods
     def VTPM_create(self, session, vtpm_struct):
@@ -1855,7 +1916,7 @@ class XendAPI(object):
             except XendError:
                 return xen_api_error(XEND_ERROR_TODO)
         else:
-            return xen_api_error(['VM_HANDLE_INVALID', vtpm_struct['VM']])
+            return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
 
     def VTPM_get_all(self, session):
         xendom = XendDomain.instance()
@@ -1897,10 +1958,10 @@ class XendAPI(object):
         xendom = XendDomain.instance()
         vm = xendom.get_vm_with_dev_uuid('console', console_ref)
         if not vm:
-            return xen_api_error(['CONSOLE_HANDLE_INVALID', console_ref])
+            return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
         cfg = vm.get_dev_xenapi_config('console', console_ref)
         if not cfg:
-            return xen_api_error(['CONSOLE_HANDLE_INVALID', console_ref])
+            return xen_api_error(['HANDLE_INVALID', 'console', console_ref])
         
         valid_console_keys = self.console_attr_ro + self.console_attr_rw + \
                              self.Base_attr_ro + self.Base_attr_rw
@@ -1915,7 +1976,8 @@ class XendAPI(object):
     def console_create(self, session, console_struct):
         xendom = XendDomain.instance()
         if not xendom.is_valid_vm(console_struct['VM']):
-            return xen_api_error(['VM_HANDLE_INVALID', console_struct['VM']])
+            return xen_api_error(['HANDLE_INVALID', 'VM',
+                                  console_struct['VM']])
         
         dom = xendom.get_vm_by_uuid(console_struct['VM'])
         try:
@@ -1972,7 +2034,7 @@ class XendAPI(object):
         sr = XendNode.instance().get_sr(sr_ref)
         if sr:
             return xen_api_success(sr.get_record())
-        return xen_api_error(['SR_HANDLE_INVALID', sr_ref])
+        return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref])
 
     # Attribute acceess
 
diff -r 9364bea18bc4 -r 202eb735b425 tools/python/xen/xm/messages/en/xen-xm.po
--- a/tools/python/xen/xm/messages/en/xen-xm.po Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/python/xen/xm/messages/en/xen-xm.po Thu Feb 22 10:15:29 2007 -0700
@@ -19,7 +19,7 @@ msgid ""
 msgid ""
 msgstr ""
 "Project-Id-Version: Xen-xm 3.0\n"
-"PO-Revision-Date: 2007-01-31 12:34+0000\n"
+"PO-Revision-Date: 2007-02-20 15:22+0000\n"
 "Last-Translator: Ewan Mellor <ewan@xxxxxxxxxxxxx>\n"
 "Language-Team: xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxx>\n"
 "MIME-Version: 1.0\n"
@@ -44,44 +44,8 @@ msgid "VALUE_NOT_SUPPORTED"
 msgid "VALUE_NOT_SUPPORTED"
 msgstr "Value \"%(2)s\" for %(1)s is not supported by this server.  The server 
said \"%(3)s\"."
 
-msgid "HOST_CPU_HANDLE_INVALID"
-msgstr "The host_cpu handle %(1)s is invalid."
-
-msgid "HOST_HANDLE_INVALID"
-msgstr "The host handle %(1)s is invalid."
-
-msgid "HOST_METRICS_HANDLE_INVALID"
-msgstr "The host_metrics handle %(1)s is invalid."
-
-msgid "PIF_HANDLE_INVALID"
-msgstr "The PIF handle %(1)s is invalid."
-
-msgid "PIF_METRICS_HANDLE_INVALID"
-msgstr "The PIF_METRICS handle %(1)s is invalid."
-
-msgid "SR_HANDLE_INVALID"
-msgstr "The SR handle %(1)s is invalid."
-
-msgid "TASK_HANDLE_INVALID"
-msgstr "The task handle %(1)s is invalid."
-
-msgid "VBD_HANDLE_INVALID"
-msgstr "The VBD handle %(1)s is invalid."
-
-msgid "VDI_HANDLE_INVALID"
-msgstr "The VDI handle %(1)s is invalid."
-
-msgid "VIF_HANDLE_INVALID"
-msgstr "The VIF handle %(1)s is invalid."
-
-msgid "VM_HANDLE_INVALID"
-msgstr "The VM handle %(1)s is invalid."
-
-msgid "VM_METRICS_HANDLE_INVALID"
-msgstr "The VM_metrics handle %(1)s is invalid."
-
-msgid "VTPM_HANDLE_INVALID"
-msgstr "The VTPM handle %(1)s is invalid."
+msgid "HANDLE_INVALID"
+msgstr "The %(1)s handle %(2)s is invalid."
 
 msgid "OPERATION_NOT_ALLOWED"
 msgstr "You attempted an operation that was not allowed."
diff -r 9364bea18bc4 -r 202eb735b425 tools/tests/test_x86_emulator.c
--- a/tools/tests/test_x86_emulator.c   Thu Feb 22 09:42:13 2007 -0700
+++ b/tools/tests/test_x86_emulator.c   Thu Feb 22 10:15:29 2007 -0700
@@ -43,7 +43,7 @@ static int read(
     case 4: *val = *(u32 *)addr; break;
     case 8: *val = *(unsigned long *)addr; break;
     }
-    return X86EMUL_CONTINUE;
+    return X86EMUL_OKAY;
 }
 
 static int write(
@@ -61,7 +61,7 @@ static int write(
     case 4: *(u32 *)addr = (u32)val; break;
     case 8: *(unsigned long *)addr = val; break;
     }
-    return X86EMUL_CONTINUE;
+    return X86EMUL_OKAY;
 }
 
 static int cmpxchg(
@@ -80,7 +80,7 @@ static int cmpxchg(
     case 4: *(u32 *)addr = (u32)new; break;
     case 8: *(unsigned long *)addr = new; break;
     }
-    return X86EMUL_CONTINUE;
+    return X86EMUL_OKAY;
 }
 
 static int cmpxchg8b(
@@ -95,7 +95,7 @@ static int cmpxchg8b(
     unsigned long addr = offset;
     ((unsigned long *)addr)[0] = new_lo;
     ((unsigned long *)addr)[1] = new_hi;
-    return X86EMUL_CONTINUE;
+    return X86EMUL_OKAY;
 }
 
 static struct x86_emulate_ops emulops = {
@@ -138,7 +138,7 @@ int main(int argc, char **argv)
     regs.eax    = (unsigned long)res;
     *res        = 0x7FFFFFFF;
     rc = x86_emulate(&ctxt, &emulops);
-    if ( (rc != 0) || 
+    if ( (rc != X86EMUL_OKAY) || 
          (*res != 0x92345677) || 
          (regs.eflags != 0xa94) ||
          (regs.eip != (unsigned long)&instr[2]) )
@@ -152,7 +152,7 @@ int main(int argc, char **argv)
     regs.ecx    = 0x12345678;
     regs.eax    = 0x7FFFFFFF;
     rc = x86_emulate(&ctxt, &emulops);
-    if ( (rc != 0) || 
+    if ( (rc != X86EMUL_OKAY) || 
          (regs.ecx != 0x12345678) ||
          (regs.eax != 0x92345677) ||
          (regs.eflags != 0xa94) ||
@@ -171,7 +171,7 @@ int main(int argc, char **argv)
 #endif
     regs.eax    = (unsigned long)res;
     rc = x86_emulate(&ctxt, &emulops);
-    if ( (rc != 0) || 
+    if ( (rc != X86EMUL_OKAY) || 
          (*res != 0x92345677) || 
          (regs.ecx != 0x8000000FUL) ||
          (regs.eip != (unsigned long)&instr[2]) )
@@ -185,7 +185,7 @@ int main(int argc, char **argv)
     regs.ecx    = ~0UL;
     regs.eax    = (unsigned long)res;
     rc = x86_emulate(&ctxt, &emulops);
-    if ( (rc != 0) || 
+    if ( (rc != X86EMUL_OKAY) || 
          (*res != 0x92345677) || 
          (regs.ecx != 0x92345677UL) ||
          (regs.eip != (unsigned long)&instr[2]) )
@@ -200,7 +200,7 @@ int main(int argc, char **argv)
     regs.ecx    = 0xAA;
     regs.ebx    = (unsigned long)res;
     rc = x86_emulate(&ctxt, &emulops);
-    if ( (rc != 0) || 
+    if ( (rc != X86EMUL_OKAY) || 
          (*res != 0x923456AA) || 
          (regs.eflags != 0x244) ||
          (regs.eax != 0x92345677UL) ||
@@ -216,7 +216,7 @@ int main(int argc, char **argv)
     regs.ecx    = 0xFF;
     regs.ebx    = (unsigned long)res;
     rc = x86_emulate(&ctxt, &emulops);
-    if ( (rc != 0) || 
+    if ( (rc != X86EMUL_OKAY) || 
          (*res != 0x923456AA) || 
          ((regs.eflags&0x240) != 0x200) ||
          (regs.eax != 0xAABBCCAA) ||
@@ -232,7 +232,7 @@ int main(int argc, char **argv)
     regs.ecx    = 0x12345678;
     regs.eax    = (unsigned long)res;
     rc = x86_emulate(&ctxt, &emulops);
-    if ( (rc != 0) || 
+    if ( (rc != X86EMUL_OKAY) || 
          (*res != 0x12345678) || 
          (regs.eflags != 0x200) ||
          (regs.ecx != 0x923456AA) ||
@@ -249,7 +249,7 @@ int main(int argc, char **argv)
     regs.ecx    = 0xDDEEFF00L;
     regs.ebx    = (unsigned long)res;
     rc = x86_emulate(&ctxt, &emulops);
-    if ( (rc != 0) || 
+    if ( (rc != X86EMUL_OKAY) || 
          (*res != 0xDDEEFF00) || 
          (regs.eflags != 0x244) ||
          (regs.eax != 0x923456AAUL) ||
@@ -266,7 +266,7 @@ int main(int argc, char **argv)
     regs.esi    = (unsigned long)res + 0;
     regs.edi    = (unsigned long)res + 2;
     rc = x86_emulate(&ctxt, &emulops);
-    if ( (rc != 0) || 
+    if ( (rc != X86EMUL_OKAY) || 
          (*res != 0x44554455) ||
          (regs.eflags != 0x200) ||
          (regs.ecx != 22) || 
@@ -283,7 +283,7 @@ int main(int argc, char **argv)
     regs.eip    = (unsigned long)&instr[0];
     regs.edi    = (unsigned long)res;
     rc = x86_emulate(&ctxt, &emulops);
-    if ( (rc != 0) ||
+    if ( (rc != X86EMUL_OKAY) ||
          (*res != 0x2233445D) ||
          ((regs.eflags&0x201) != 0x201) ||
          (regs.eip != (unsigned long)&instr[4]) )
@@ -298,7 +298,7 @@ int main(int argc, char **argv)
     regs.eax    = -32;
     regs.edi    = (unsigned long)(res+1);
     rc = x86_emulate(&ctxt, &emulops);
-    if ( (rc != 0) ||
+    if ( (rc != X86EMUL_OKAY) ||
          (*res != 0x2233445E) ||
          ((regs.eflags&0x201) != 0x201) ||
          (regs.eip != (unsigned long)&instr[3]) )
@@ -318,7 +318,7 @@ int main(int argc, char **argv)
     regs.eip    = (unsigned long)&instr[0];
     regs.edi    = (unsigned long)res;
     rc = x86_emulate(&ctxt, &emulops);
-    if ( (rc != 0) ||
+    if ( (rc != X86EMUL_OKAY) ||
          (res[0] != 0x9999AAAA) ||
          (res[1] != 0xCCCCFFFF) ||
          ((regs.eflags&0x240) != 0x240) ||
@@ -332,7 +332,7 @@ int main(int argc, char **argv)
     regs.eip    = (unsigned long)&instr[0];
     regs.edi    = (unsigned long)res;
     rc = x86_emulate(&ctxt, &emulops);
-    if ( (rc != 0) || 
+    if ( (rc != X86EMUL_OKAY) || 
          (res[0] != 0x9999AAAA) ||
          (res[1] != 0xCCCCFFFF) ||
          (regs.eax != 0x9999AAAA) ||
@@ -350,7 +350,7 @@ int main(int argc, char **argv)
     regs.eax    = (unsigned long)res;
     *res        = 0x82;
     rc = x86_emulate(&ctxt, &emulops);
-    if ( (rc != 0) ||
+    if ( (rc != X86EMUL_OKAY) ||
          (*res != 0x82) ||
          (regs.ecx != 0xFFFFFF82) ||
          ((regs.eflags&0x240) != 0x200) ||
@@ -366,7 +366,7 @@ int main(int argc, char **argv)
     regs.eax    = (unsigned long)res;
     *res        = 0x1234aa82;
     rc = x86_emulate(&ctxt, &emulops);
-    if ( (rc != 0) ||
+    if ( (rc != X86EMUL_OKAY) ||
          (*res != 0x1234aa82) ||
          (regs.ecx != 0xaa82) ||
          ((regs.eflags&0x240) != 0x200) ||
@@ -382,7 +382,7 @@ int main(int argc, char **argv)
     regs.eax    = 0x12345678;
     *res        = 0x11111111;
     rc = x86_emulate(&ctxt, &emulops);
-    if ( (rc != 0) ||
+    if ( (rc != X86EMUL_OKAY) ||
          (*res != 0x11116789) ||
          (regs.eax != 0x12341111) ||
          ((regs.eflags&0x240) != 0x200) ||
@@ -396,7 +396,7 @@ int main(int argc, char **argv)
     regs.eip    = (unsigned long)&instr[0];
     regs.eax    = 0x00000000;
     rc = x86_emulate(&ctxt, &emulops);
-    if ( (rc != 0) ||
+    if ( (rc != X86EMUL_OKAY) ||
          (regs.eax != 0x0000ffff) ||
          ((regs.eflags&0x240) != 0x200) ||
          (regs.eip != (unsigned long)&instr[2]) )
@@ -410,7 +410,7 @@ int main(int argc, char **argv)
     regs.eax    = 0x12345678;
     regs.ebp    = 0xaaaaaaaa;
     rc = x86_emulate(&ctxt, &emulops);
-    if ( (rc != 0) ||
+    if ( (rc != X86EMUL_OKAY) ||
          (regs.eax != 0xaaaaaab2) ||
          ((regs.eflags&0x240) != 0x200) ||
          (regs.eip != (unsigned long)&instr[3]) )
@@ -454,7 +454,7 @@ int main(int argc, char **argv)
         bcdres_emul |= (regs.eflags & EFLG_SF) ? 0x400 : 0;
         bcdres_emul |= (regs.eflags & EFLG_CF) ? 0x200 : 0;
         bcdres_emul |= (regs.eflags & EFLG_AF) ? 0x100 : 0;
-        if ( (rc != 0) || (regs.eax > 255) ||
+        if ( (rc != X86EMUL_OKAY) || (regs.eax > 255) ||
              (regs.eip != (unsigned long)&instr[1]) )
             goto fail;
 
@@ -501,7 +501,7 @@ int main(int argc, char **argv)
         if ( (i++ & 8191) == 0 )
             printf(".");
         rc = x86_emulate(&ctxt, &emulops);
-        if ( rc != 0 )
+        if ( rc != X86EMUL_OKAY )
         {
             printf("failed at %%eip == %08x\n", (unsigned int)regs.eip);
             return 1;
diff -r 9364bea18bc4 -r 202eb735b425 xen/acm/acm_chinesewall_hooks.c
--- a/xen/acm/acm_chinesewall_hooks.c   Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/acm/acm_chinesewall_hooks.c   Thu Feb 22 10:15:29 2007 -0700
@@ -194,19 +194,18 @@ chwall_init_state(struct acm_chwall_poli
     int violation = 0, i, j;
     struct chwall_ssid *chwall_ssid;
     ssidref_t chwall_ssidref;
-    struct domain **pd;
-
-    write_lock(&domlist_lock);
+    struct domain *d;
+
+    spin_lock(&domlist_update_lock);
     /* go through all domains and adjust policy as if this domain was started 
now */
-    pd = &domain_list;
-    for (pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list)
+    for_each_domain ( d )
     {
         chwall_ssid =
             GET_SSIDP(ACM_CHINESE_WALL_POLICY,
-                      (struct acm_ssid_domain *) (*pd)->ssid);
+                      (struct acm_ssid_domain *)d->ssid);
         chwall_ssidref = chwall_ssid->chwall_ssidref;
         traceprintk("%s: validating policy for domain %x (chwall-REF=%x).\n",
-                    __func__, (*pd)->domain_id, chwall_ssidref);
+                    __func__, d->domain_id, chwall_ssidref);
         /* a) adjust types ref-count for running domains */
         for (i = 0; i < chwall_buf->chwall_max_types; i++)
             running_types[i] +=
@@ -247,7 +246,7 @@ chwall_init_state(struct acm_chwall_poli
         }
     }
  out:
-    write_unlock(&domlist_lock);
+    spin_unlock(&domlist_update_lock);
     return violation;
     /* returning "violation != 0" means that the currently running set of 
domains would
      * not be possible if the new policy had been enforced before starting 
them; for chinese
diff -r 9364bea18bc4 -r 202eb735b425 xen/acm/acm_simple_type_enforcement_hooks.c
--- a/xen/acm/acm_simple_type_enforcement_hooks.c       Thu Feb 22 09:42:13 
2007 -0700
+++ b/xen/acm/acm_simple_type_enforcement_hooks.c       Thu Feb 22 10:15:29 
2007 -0700
@@ -175,36 +175,37 @@ ste_init_state(struct acm_ste_policy_buf
     int violation = 1;
     struct ste_ssid *ste_ssid, *ste_rssid;
     ssidref_t ste_ssidref, ste_rssidref;
-    struct domain **pd, *rdom;
+    struct domain *d, *rdom;
     domid_t rdomid;
     struct grant_entry sha_copy;
     int port, i;
 
-    read_lock(&domlist_lock); /* go by domain? or directly by global? 
event/grant list */
+    rcu_read_lock(&domlist_read_lock);
+    /* go by domain? or directly by global? event/grant list */
     /* go through all domains and adjust policy as if this domain was started 
now */
-    pd = &domain_list;
-    for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
+    for_each_domain ( d )
+    {
         ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 
-                             (struct acm_ssid_domain *)(*pd)->ssid);
+                             (struct acm_ssid_domain *)d->ssid);
         ste_ssidref = ste_ssid->ste_ssidref;
         traceprintk("%s: validating policy for eventch domain %x 
(ste-Ref=%x).\n",
-                    __func__, (*pd)->domain_id, ste_ssidref);
+                    __func__, d->domain_id, ste_ssidref);
         /* a) check for event channel conflicts */
         for (port=0; port < NR_EVTCHN_BUCKETS; port++) {
-            spin_lock(&(*pd)->evtchn_lock);
-            if ((*pd)->evtchn[port] == NULL) {
-                spin_unlock(&(*pd)->evtchn_lock);
+            spin_lock(&d->evtchn_lock);
+            if (d->evtchn[port] == NULL) {
+                spin_unlock(&d->evtchn_lock);
                 continue;
             }
-            if ((*pd)->evtchn[port]->state == ECS_INTERDOMAIN) {
-                rdom = (*pd)->evtchn[port]->u.interdomain.remote_dom;
+            if (d->evtchn[port]->state == ECS_INTERDOMAIN) {
+                rdom = d->evtchn[port]->u.interdomain.remote_dom;
                 rdomid = rdom->domain_id;
                 /* rdom now has remote domain */
                 ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 
                                       (struct acm_ssid_domain *)(rdom->ssid));
                 ste_rssidref = ste_rssid->ste_ssidref;
-            } else if ((*pd)->evtchn[port]->state == ECS_UNBOUND) {
-                rdomid = (*pd)->evtchn[port]->u.unbound.remote_domid;
+            } else if (d->evtchn[port]->state == ECS_UNBOUND) {
+                rdomid = d->evtchn[port]->u.unbound.remote_domid;
                 if ((rdom = get_domain_by_id(rdomid)) == NULL) {
                     printk("%s: Error finding domain to id %x!\n", __func__, 
rdomid);
                     goto out;
@@ -215,36 +216,36 @@ ste_init_state(struct acm_ste_policy_buf
                 ste_rssidref = ste_rssid->ste_ssidref;
                 put_domain(rdom);
             } else {
-                spin_unlock(&(*pd)->evtchn_lock);
+                spin_unlock(&d->evtchn_lock);
                 continue; /* port unused */
             }
-            spin_unlock(&(*pd)->evtchn_lock);
+            spin_unlock(&d->evtchn_lock);
 
             /* rdom now has remote domain */
             ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 
                                   (struct acm_ssid_domain *)(rdom->ssid));
             ste_rssidref = ste_rssid->ste_ssidref;
             traceprintk("%s: eventch: domain %x (ssidref %x) --> domain %x 
(rssidref %x) used (port %x).\n", 
-                        __func__, (*pd)->domain_id, ste_ssidref, 
rdom->domain_id, ste_rssidref, port);  
+                        __func__, d->domain_id, ste_ssidref, rdom->domain_id, 
ste_rssidref, port);  
             /* check whether on subj->ssid, obj->ssid share a common type*/
             if (!have_common_type(ste_ssidref, ste_rssidref)) {
                 printkd("%s: Policy violation in event channel domain %x -> 
domain %x.\n",
-                        __func__, (*pd)->domain_id, rdomid);
+                        __func__, d->domain_id, rdomid);
                 goto out;
             }
         } 
         /* b) check for grant table conflicts on shared pages */
-        spin_lock(&(*pd)->grant_table->lock);
-        for ( i = 0; i < nr_grant_entries((*pd)->grant_table); i++ ) {
+        spin_lock(&d->grant_table->lock);
+        for ( i = 0; i < nr_grant_entries(d->grant_table); i++ ) {
 #define SPP (PAGE_SIZE / sizeof(struct grant_entry))
-            sha_copy = (*pd)->grant_table->shared[i/SPP][i%SPP];
+            sha_copy = d->grant_table->shared[i/SPP][i%SPP];
             if ( sha_copy.flags ) {
                 printkd("%s: grant dom (%hu) SHARED (%d) flags:(%hx) dom:(%hu) 
frame:(%lx)\n",
-                        __func__, (*pd)->domain_id, i, sha_copy.flags, 
sha_copy.domid, 
+                        __func__, d->domain_id, i, sha_copy.flags, 
sha_copy.domid, 
                         (unsigned long)sha_copy.frame);
                 rdomid = sha_copy.domid;
                 if ((rdom = get_domain_by_id(rdomid)) == NULL) {
-                    spin_unlock(&(*pd)->grant_table->lock);
+                    spin_unlock(&d->grant_table->lock);
                     printkd("%s: domain not found ERROR!\n", __func__);
                     goto out;
                 };
@@ -254,18 +255,18 @@ ste_init_state(struct acm_ste_policy_buf
                 ste_rssidref = ste_rssid->ste_ssidref;
                 put_domain(rdom);
                 if (!have_common_type(ste_ssidref, ste_rssidref)) {
-                    spin_unlock(&(*pd)->grant_table->lock);
+                    spin_unlock(&d->grant_table->lock);
                     printkd("%s: Policy violation in grant table sharing 
domain %x -> domain %x.\n",
-                            __func__, (*pd)->domain_id, rdomid);
+                            __func__, d->domain_id, rdomid);
                     goto out;
                 }
             }
         }
-        spin_unlock(&(*pd)->grant_table->lock);
+        spin_unlock(&d->grant_table->lock);
     }
     violation = 0;
  out:
-    read_unlock(&domlist_lock);
+    rcu_read_unlock(&domlist_read_lock);
     return violation;
     /* returning "violation != 0" means that existing sharing between domains 
would not 
      * have been allowed if the new policy had been enforced before the 
sharing; for ste, 
@@ -281,7 +282,7 @@ ste_set_policy(u8 *buf, u32 buf_size)
     struct acm_ste_policy_buffer *ste_buf = (struct acm_ste_policy_buffer 
*)buf;
     void *ssidrefsbuf;
     struct ste_ssid *ste_ssid;
-    struct domain **pd;
+    struct domain *d;
     int i;
 
     if (buf_size < sizeof(struct acm_ste_policy_buffer))
@@ -326,15 +327,14 @@ ste_set_policy(u8 *buf, u32 buf_size)
     ste_bin_pol.ssidrefs = (domaintype_t *)ssidrefsbuf;
 
     /* clear all ste caches */
-    read_lock(&domlist_lock);
-    pd = &domain_list;
-    for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
+    rcu_read_lock(&domlist_read_lock);
+    for_each_domain ( d ) {
         ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 
-                             (struct acm_ssid_domain *)(*pd)->ssid);
+                             (struct acm_ssid_domain *)(d)->ssid);
         for (i=0; i<ACM_TE_CACHE_SIZE; i++)
             ste_ssid->ste_cache[i].valid = ACM_STE_free;
     }
-    read_unlock(&domlist_lock);
+    rcu_read_unlock(&domlist_read_lock);
     return ACM_OK;
 
  error_free:
@@ -436,14 +436,14 @@ clean_id_from_cache(domid_t id)
 {
     struct ste_ssid *ste_ssid;
     int i;
-    struct domain **pd;
+    struct domain *d;
     struct acm_ssid_domain *ssid;
 
     printkd("deleting cache for dom %x.\n", id);
-    read_lock(&domlist_lock); /* look through caches of all domains */
-    pd = &domain_list;
-    for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
-        ssid = (struct acm_ssid_domain *)((*pd)->ssid);
+    rcu_read_lock(&domlist_read_lock);
+    /* look through caches of all domains */
+    for_each_domain ( d ) {
+        ssid = (struct acm_ssid_domain *)(d->ssid);
 
         if (ssid == NULL)
             continue; /* hanging domain structure, no ssid any more ... */
@@ -459,7 +459,7 @@ clean_id_from_cache(domid_t id)
                 ste_ssid->ste_cache[i].valid = ACM_STE_free;
     }
  out:
-    read_unlock(&domlist_lock);
+    rcu_read_unlock(&domlist_read_lock);
 }
 
 /***************************
diff -r 9364bea18bc4 -r 202eb735b425 xen/arch/ia64/linux-xen/mca.c
--- a/xen/arch/ia64/linux-xen/mca.c     Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/arch/ia64/linux-xen/mca.c     Thu Feb 22 10:15:29 2007 -0700
@@ -790,6 +790,7 @@ init_handler_platform (pal_min_state_are
                        /* this route is for dump routine */
                        unw_init_running(try_crashdump, pt);
                } else {
+                       rcu_read_lock(&domlist_read_lock);
                        for_each_domain(d) {
                                for_each_vcpu(d, v) {
                                        printk("Backtrace of current vcpu "
@@ -798,6 +799,7 @@ init_handler_platform (pal_min_state_are
                                        show_stack(v, NULL);
                                }
                        }
+                       rcu_read_unlock(&domlist_read_lock);
                }
        }
        unw_init_running(freeze_cpu_osinit, NULL);
diff -r 9364bea18bc4 -r 202eb735b425 xen/arch/ia64/linux-xen/perfmon.c
--- a/xen/arch/ia64/linux-xen/perfmon.c Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/arch/ia64/linux-xen/perfmon.c Thu Feb 22 10:15:29 2007 -0700
@@ -7225,7 +7225,6 @@ DEFINE_PER_CPU(pfm_context_t*, xenpfm_co
 /*
  * note: some functions mask interrupt with this lock held
  * so that this lock can't be locked from interrupt handler.
- * lock order domlist_lock => xenpfm_context_lock
  */
 DEFINE_SPINLOCK(xenpfm_context_lock);
 
@@ -7507,10 +7506,8 @@ xenpfm_context_unload(void)
                arg.error[cpu] = 0;
 
        BUG_ON(in_irq());
-       read_lock(&domlist_lock);
        spin_lock(&xenpfm_context_lock);
        error = xenpfm_start_stop_locked(0);
-       read_unlock(&domlist_lock);
        if (error) {
                spin_unlock(&xenpfm_context_lock);
                return error;
@@ -7688,10 +7685,11 @@ xenpfm_start_stop_locked(int is_start)
        while (atomic_read(&arg.started) != cpus)
                cpu_relax();
 
-       for_each_domain(d) {
+       rcu_read_lock(&domlist_read_lock);
+       for_each_domain(d)
                for_each_vcpu(d, v)
                        xenpfm_start_stop_vcpu(v, is_start);
-       }
+       rcu_read_unlock(&domlist_read_lock);
 
        arg.error[smp_processor_id()] = __xenpfm_start_stop(is_start);
        atomic_inc(&arg.finished);
@@ -7716,11 +7714,9 @@ xenpfm_start_stop(int is_start)
        int error;
        
        BUG_ON(in_irq());
-       read_lock(&domlist_lock);
        spin_lock(&xenpfm_context_lock);
-       error =xenpfm_start_stop_locked(is_start);
+       error = xenpfm_start_stop_locked(is_start);
        spin_unlock(&xenpfm_context_lock);
-       read_unlock(&domlist_lock);
 
        return error;
 }
diff -r 9364bea18bc4 -r 202eb735b425 xen/arch/powerpc/audit.c
--- a/xen/arch/powerpc/audit.c  Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/arch/powerpc/audit.c  Thu Feb 22 10:15:29 2007 -0700
@@ -34,8 +34,10 @@ void audit_domains(void)
 void audit_domains(void)
 {
     struct domain *d;
+    rcu_read_lock(&domlist_read_lock);
     for_each_domain ( d )
         audit_domain(d);
+    rcu_read_unlock(&domlist_read_lock);
 }
 
 void audit_domains_key(unsigned char key)
diff -r 9364bea18bc4 -r 202eb735b425 xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c     Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/arch/x86/domctl.c     Thu Feb 22 10:15:29 2007 -0700
@@ -441,6 +441,10 @@ void arch_get_info_guest(struct vcpu *v,
         XLAT_vcpu_guest_context(c.cmp, &v->arch.guest_context);
 #endif
 
+    c(flags &= ~(VGCF_i387_valid|VGCF_in_kernel));
+    if ( test_bit(_VCPUF_fpu_initialised, &v->vcpu_flags) )
+        c(flags |= VGCF_i387_valid);
+
     if ( is_hvm_vcpu(v) )
     {
         if ( !IS_COMPAT(v->domain) )
@@ -464,23 +468,21 @@ void arch_get_info_guest(struct vcpu *v,
         /* IOPL privileges are virtualised: merge back into returned eflags. */
         BUG_ON((c(user_regs.eflags) & EF_IOPL) != 0);
         c(user_regs.eflags |= v->arch.iopl << 12);
-    }
-
-    c(flags &= ~(VGCF_i387_valid|VGCF_in_kernel));
-    if ( test_bit(_VCPUF_fpu_initialised, &v->vcpu_flags) )
-        c(flags |= VGCF_i387_valid);
-    if ( guest_kernel_mode(v, &v->arch.guest_context.user_regs) )
-        c(flags |= VGCF_in_kernel);
-
-    if ( !IS_COMPAT(v->domain) )
-        c.nat->ctrlreg[3] = 
xen_pfn_to_cr3(pagetable_get_pfn(v->arch.guest_table));
-#ifdef CONFIG_COMPAT
-    else
-    {
-        l4_pgentry_t *l4e = __va(pagetable_get_paddr(v->arch.guest_table));
-        c.cmp->ctrlreg[3] = compat_pfn_to_cr3(l4e_get_pfn(*l4e));
-    }
-#endif
+
+        if ( !IS_COMPAT(v->domain) )
+            c.nat->ctrlreg[3] = xen_pfn_to_cr3(
+                pagetable_get_pfn(v->arch.guest_table));
+#ifdef CONFIG_COMPAT
+        else
+        {
+            l4_pgentry_t *l4e = __va(pagetable_get_paddr(v->arch.guest_table));
+            c.cmp->ctrlreg[3] = compat_pfn_to_cr3(l4e_get_pfn(*l4e));
+        }
+#endif
+
+        if ( guest_kernel_mode(v, &v->arch.guest_context.user_regs) )
+            c(flags |= VGCF_in_kernel);
+    }
 
     c(vm_assist = v->domain->vm_assist);
 #undef c
diff -r 9364bea18bc4 -r 202eb735b425 xen/arch/x86/extable.c
--- a/xen/arch/x86/extable.c    Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/arch/x86/extable.c    Thu Feb 22 10:15:29 2007 -0700
@@ -1,13 +1,8 @@
 
 #include <xen/config.h>
+#include <xen/perfc.h>
 #include <xen/spinlock.h>
 #include <asm/uaccess.h>
-
-#ifdef PERF_COUNTERS
-#include <xen/sched.h>
-#include <xen/perfc.h>
-#include <asm/current.h>
-#endif
 
 extern struct exception_table_entry __start___ex_table[];
 extern struct exception_table_entry __stop___ex_table[];
@@ -74,10 +69,10 @@ search_pre_exception_table(struct cpu_us
     unsigned long addr = (unsigned long)regs->eip;
     unsigned long fixup = search_one_table(
         __start___pre_ex_table, __stop___pre_ex_table-1, addr);
-    dprintk(XENLOG_INFO, "Pre-exception: %p -> %p\n", _p(addr), _p(fixup));
-#ifdef PERF_COUNTERS
     if ( fixup )
+    {
+        dprintk(XENLOG_INFO, "Pre-exception: %p -> %p\n", _p(addr), _p(fixup));
         perfc_incrc(exception_fixed);
-#endif
+    }
     return fixup;
 }
diff -r 9364bea18bc4 -r 202eb735b425 xen/arch/x86/hvm/io.c
--- a/xen/arch/x86/hvm/io.c     Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/arch/x86/hvm/io.c     Thu Feb 22 10:15:29 2007 -0700
@@ -533,6 +533,7 @@ static void hvm_mmio_assist(struct cpu_u
         break;
 
     case INSTR_LODS:
+        set_reg_value(size, 0, 0, regs, p->data);
         sign = p->df ? -1 : 1;
         regs->esi += sign * p->count * p->size;
         if (mmio_opp->flags & REPZ)
@@ -553,6 +554,7 @@ static void hvm_mmio_assist(struct cpu_u
             diff = (unsigned long) p->data & value;
             set_reg_value(size, index, 0, regs, diff);
         }
+        break;
 
     case INSTR_ADD:
         if (src & REGISTER) {
diff -r 9364bea18bc4 -r 202eb735b425 xen/arch/x86/hvm/platform.c
--- a/xen/arch/x86/hvm/platform.c       Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/arch/x86/hvm/platform.c       Thu Feb 22 10:15:29 2007 -0700
@@ -1136,6 +1136,7 @@ void handle_mmio(unsigned long gpa)
          * Since the source is always in (contiguous) mmio space we don't
          * need to break it up into pages.
          */
+        mmio_op->operand[0] = mk_operand(op_size, 0, 0, REGISTER);
         send_mmio_req(IOREQ_TYPE_COPY, gpa,
                       GET_REPEAT_COUNT(), op_size, 0, IOREQ_READ, df, 0);
         break;
diff -r 9364bea18bc4 -r 202eb735b425 xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c       Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/arch/x86/hvm/svm/vmcb.c       Thu Feb 22 10:15:29 2007 -0700
@@ -330,6 +330,9 @@ static void vmcb_dump(unsigned char ch)
     struct vcpu *v;
     
     printk("*********** VMCB Areas **************\n");
+
+    rcu_read_lock(&domlist_read_lock);
+
     for_each_domain ( d )
     {
         if ( !is_hvm_domain(d) )
@@ -341,6 +344,8 @@ static void vmcb_dump(unsigned char ch)
             svm_dump_vmcb("key_handler", v->arch.hvm_svm.vmcb);
         }
     }
+
+    rcu_read_unlock(&domlist_read_lock);
 
     printk("**************************************\n");
 }
diff -r 9364bea18bc4 -r 202eb735b425 xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c       Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/arch/x86/hvm/vmx/vmcs.c       Thu Feb 22 10:15:29 2007 -0700
@@ -567,6 +567,9 @@ static void vmcs_dump(unsigned char ch)
     struct vcpu *v;
     
     printk("*********** VMCS Areas **************\n");
+
+    rcu_read_lock(&domlist_read_lock);
+
     for_each_domain ( d )
     {
         if ( !is_hvm_domain(d) )
@@ -581,6 +584,8 @@ static void vmcs_dump(unsigned char ch)
         }
     }
 
+    rcu_read_unlock(&domlist_read_lock);
+
     printk("**************************************\n");
 }
 
diff -r 9364bea18bc4 -r 202eb735b425 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Thu Feb 22 10:15:29 2007 -0700
@@ -696,7 +696,7 @@ static void vmx_store_cpu_guest_regs(
     {
         crs[0] = v->arch.hvm_vmx.cpu_shadow_cr0;
         crs[2] = v->arch.hvm_vmx.cpu_cr2;
-        crs[3] = __vmread(GUEST_CR3);
+        crs[3] = v->arch.hvm_vmx.cpu_cr3;
         crs[4] = v->arch.hvm_vmx.cpu_shadow_cr4;
     }
 
diff -r 9364bea18bc4 -r 202eb735b425 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/arch/x86/mm.c Thu Feb 22 10:15:29 2007 -0700
@@ -3151,10 +3151,10 @@ static int ptwr_emulated_read(
     if ( (rc = copy_from_user((void *)val, (void *)addr, bytes)) != 0 )
     {
         propagate_page_fault(addr + bytes - rc, 0); /* read fault */
-        return X86EMUL_PROPAGATE_FAULT;
-    }
-
-    return X86EMUL_CONTINUE;
+        return X86EMUL_EXCEPTION;
+    }
+
+    return X86EMUL_OKAY;
 }
 
 static int ptwr_emulated_update(
@@ -3190,7 +3190,7 @@ static int ptwr_emulated_update(
         if ( (rc = copy_from_user(&full, (void *)addr, sizeof(paddr_t))) != 0 )
         {
             propagate_page_fault(addr+sizeof(paddr_t)-rc, 0); /* read fault */
-            return X86EMUL_PROPAGATE_FAULT;
+            return X86EMUL_EXCEPTION;
         }
         /* Mask out bits provided by caller. */
         full &= ~((((paddr_t)1 << (bytes*8)) - 1) << (offset*8));
@@ -3273,7 +3273,7 @@ static int ptwr_emulated_update(
     /* Finally, drop the old PTE. */
     put_page_from_l1e(gl1e_to_ml1e(d, ol1e), d);
 
-    return X86EMUL_CONTINUE;
+    return X86EMUL_OKAY;
 }
 
 static int ptwr_emulated_write(
@@ -3333,6 +3333,7 @@ int ptwr_do_page_fault(struct vcpu *v, u
     struct page_info *page;
     l1_pgentry_t      pte;
     struct ptwr_emulate_ctxt ptwr_ctxt;
+    int rc;
 
     LOCK_BIGLOCK(d);
 
@@ -3357,7 +3358,9 @@ int ptwr_do_page_fault(struct vcpu *v, u
         IS_COMPAT(d) ? 32 : BITS_PER_LONG;
     ptwr_ctxt.cr2 = addr;
     ptwr_ctxt.pte = pte;
-    if ( x86_emulate(&ptwr_ctxt.ctxt, &ptwr_emulate_ops) )
+
+    rc = x86_emulate(&ptwr_ctxt.ctxt, &ptwr_emulate_ops);
+    if ( rc == X86EMUL_UNHANDLEABLE )
         goto bail;
 
     UNLOCK_BIGLOCK(d);
diff -r 9364bea18bc4 -r 202eb735b425 xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c   Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/arch/x86/mm/shadow/common.c   Thu Feb 22 10:15:29 2007 -0700
@@ -191,7 +191,7 @@ static int hvm_translate_linear_addr(
  gpf:
     /* Inject #GP(0). */
     hvm_inject_exception(TRAP_gp_fault, 0, 0);
-    return X86EMUL_PROPAGATE_FAULT;
+    return X86EMUL_EXCEPTION;
 }
 
 static int
@@ -216,7 +216,7 @@ hvm_read(enum x86_segment seg,
     //        In this case, that is only a user vs supervisor access check.
     //
     if ( (rc = hvm_copy_from_guest_virt(val, addr, bytes)) == 0 )
-        return X86EMUL_CONTINUE;
+        return X86EMUL_OKAY;
 
     /* If we got here, there was nothing mapped here, or a bad GFN 
      * was mapped here.  This should never happen: we're here because
@@ -226,7 +226,7 @@ hvm_read(enum x86_segment seg,
     if ( access_type == hvm_access_insn_fetch )
         errcode |= PFEC_insn_fetch;
     hvm_inject_exception(TRAP_page_fault, errcode, addr + bytes - rc);
-    return X86EMUL_PROPAGATE_FAULT;
+    return X86EMUL_EXCEPTION;
 }
 
 static int
@@ -259,7 +259,7 @@ hvm_emulate_insn_fetch(enum x86_segment 
     /* Hit the cache. Simple memcpy. */
     *val = 0;
     memcpy(val, &sh_ctxt->insn_buf[insn_off], bytes);
-    return X86EMUL_CONTINUE;
+    return X86EMUL_OKAY;
 }
 
 static int
@@ -352,10 +352,10 @@ pv_emulate_read(enum x86_segment seg,
     if ( (rc = copy_from_user((void *)val, (void *)offset, bytes)) != 0 )
     {
         propagate_page_fault(offset + bytes - rc, 0); /* read fault */
-        return X86EMUL_PROPAGATE_FAULT;
-    }
-
-    return X86EMUL_CONTINUE;
+        return X86EMUL_EXCEPTION;
+    }
+
+    return X86EMUL_OKAY;
 }
 
 static int
@@ -890,13 +890,17 @@ static void shadow_blow_all_tables(unsig
 {
     struct domain *d;
     printk("'%c' pressed -> blowing all shadow tables\n", c);
+    rcu_read_lock(&domlist_read_lock);
     for_each_domain(d)
+    {
         if ( shadow_mode_enabled(d) && d->vcpu[0] != NULL )
         {
             shadow_lock(d);
             shadow_blow_tables(d);
             shadow_unlock(d);
         }
+    }
+    rcu_read_unlock(&domlist_read_lock);
 }
 
 /* Register this function in the Xen console keypress table */
diff -r 9364bea18bc4 -r 202eb735b425 xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c    Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/arch/x86/mm/shadow/multi.c    Thu Feb 22 10:15:29 2007 -0700
@@ -2911,8 +2911,16 @@ static int sh_page_fault(struct vcpu *v,
      * page is no longer a page table. This behaviour differs from native, but
      * it seems very unlikely that any OS grants user access to page tables.
      */
-    if ( (regs->error_code & PFEC_user_mode) ||
-         x86_emulate(&emul_ctxt.ctxt, emul_ops) )
+    r = X86EMUL_UNHANDLEABLE;
+    if ( !(regs->error_code & PFEC_user_mode) )
+        r = x86_emulate(&emul_ctxt.ctxt, emul_ops);
+
+    /*
+     * NB. We do not unshadow on X86EMUL_EXCEPTION. It's not clear that it
+     * would be a good unshadow hint. If we *do* decide to unshadow-on-fault
+     * then it must be 'failable': we cannot require the unshadow to succeed.
+     */
+    if ( r == X86EMUL_UNHANDLEABLE )
     {
         SHADOW_PRINTK("emulator failure, unshadowing mfn %#lx\n", 
                        mfn_x(gmfn));
@@ -3956,7 +3964,7 @@ sh_x86_emulate_write(struct vcpu *v, uns
     ASSERT(((vaddr & ~PAGE_MASK) + bytes) <= PAGE_SIZE);
 
     if ( (addr = emulate_map_dest(v, vaddr, sh_ctxt, &mfn)) == NULL )
-        return X86EMUL_PROPAGATE_FAULT;
+        return X86EMUL_EXCEPTION;
 
     skip = safe_not_to_verify_write(mfn, addr, src, bytes);
     memcpy(addr, src, bytes);
@@ -3968,7 +3976,7 @@ sh_x86_emulate_write(struct vcpu *v, uns
 
     sh_unmap_domain_page(addr);
     shadow_audit_tables(v);
-    return X86EMUL_CONTINUE;
+    return X86EMUL_OKAY;
 }
 
 int
@@ -3979,7 +3987,7 @@ sh_x86_emulate_cmpxchg(struct vcpu *v, u
     mfn_t mfn;
     void *addr;
     unsigned long prev;
-    int rv = X86EMUL_CONTINUE, skip;
+    int rv = X86EMUL_OKAY, skip;
 
     ASSERT(shadow_locked_by_me(v->domain));
     ASSERT(bytes <= sizeof(unsigned long));
@@ -3988,7 +3996,7 @@ sh_x86_emulate_cmpxchg(struct vcpu *v, u
         return X86EMUL_UNHANDLEABLE;
 
     if ( (addr = emulate_map_dest(v, vaddr, sh_ctxt, &mfn)) == NULL )
-        return X86EMUL_PROPAGATE_FAULT;
+        return X86EMUL_EXCEPTION;
 
     skip = safe_not_to_verify_write(mfn, &new, &old, bytes);
 
@@ -4032,7 +4040,7 @@ sh_x86_emulate_cmpxchg8b(struct vcpu *v,
     mfn_t mfn;
     void *addr;
     u64 old, new, prev;
-    int rv = X86EMUL_CONTINUE, skip;
+    int rv = X86EMUL_OKAY, skip;
 
     ASSERT(shadow_locked_by_me(v->domain));
 
@@ -4040,7 +4048,7 @@ sh_x86_emulate_cmpxchg8b(struct vcpu *v,
         return X86EMUL_UNHANDLEABLE;
 
     if ( (addr = emulate_map_dest(v, vaddr, sh_ctxt, &mfn)) == NULL )
-        return X86EMUL_PROPAGATE_FAULT;
+        return X86EMUL_EXCEPTION;
 
     old = (((u64) old_hi) << 32) | (u64) old_lo;
     new = (((u64) new_hi) << 32) | (u64) new_lo;
diff -r 9364bea18bc4 -r 202eb735b425 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/arch/x86/time.c       Thu Feb 22 10:15:29 2007 -0700
@@ -720,10 +720,10 @@ void do_settime(unsigned long secs, unsi
     wc_nsec = _wc_nsec = (u32)y;
     spin_unlock(&wc_lock);
 
-    read_lock(&domlist_lock);
+    rcu_read_lock(&domlist_read_lock);
     for_each_domain ( d )
         update_domain_wallclock_time(d);
-    read_unlock(&domlist_lock);
+    rcu_read_unlock(&domlist_read_lock);
 }
 
 static void local_time_calibration(void *unused)
diff -r 9364bea18bc4 -r 202eb735b425 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/arch/x86/traps.c      Thu Feb 22 10:15:29 2007 -0700
@@ -618,39 +618,77 @@ static int emulate_forced_invalid_op(str
 
 asmlinkage int do_invalid_op(struct cpu_user_regs *regs)
 {
-    int rc;
+    struct bug_frame bug;
+    struct bug_frame_str bug_str;
+    char *filename, *predicate, *eip = (char *)regs->eip;
+    int rc, id, lineno;
 
     DEBUGGER_trap_entry(TRAP_invalid_op, regs);
 
-    if ( unlikely(!guest_mode(regs)) )
-    {
-        struct bug_frame bug;
-        if ( (__copy_from_user(&bug, (char *)regs->eip, sizeof(bug)) == 0) &&
-             (memcmp(bug.ud2, "\xf\xb",    sizeof(bug.ud2)) == 0) &&
-             (memcmp(bug.mov, BUG_MOV_STR, sizeof(bug.mov)) == 0) &&
-             (bug.ret == 0xc2) )
-        {
-            char *filename = (char *)bug.filename;
-            unsigned int line = bug.line & 0x7fff;
-            int is_bug = !(bug.line & 0x8000);
-            printk("Xen %s at %.50s:%d\n",
-                   is_bug ? "BUG" : "State Dump", filename, line);
-            if ( !is_bug )
-            {
-                show_execution_state(regs);
-                regs->eip += sizeof(bug);
-                return EXCRET_fault_fixed;
-            }
-        }
+    if ( likely(guest_mode(regs)) )
+    {
+        if ( (rc = emulate_forced_invalid_op(regs)) != 0 )
+            return rc;
+        return do_guest_trap(TRAP_invalid_op, regs, 0);
+    }
+
+    if ( !is_kernel(eip) ||
+         __copy_from_user(&bug, eip, sizeof(bug)) ||
+         memcmp(bug.ud2, "\xf\xb", sizeof(bug.ud2)) ||
+         (bug.ret != 0xc2) )
+        goto die;
+
+    id = bug.id & 3;
+    if ( id == BUGFRAME_rsvd )
+        goto die;
+
+    if ( id == BUGFRAME_dump )
+    {
+        show_execution_state(regs);
+        regs->eip += sizeof(bug);
+        return EXCRET_fault_fixed;
+    }
+
+    /* BUG() or ASSERT(): decode the filename pointer and line number. */
+    ASSERT((id == BUGFRAME_bug) || (id == BUGFRAME_assert));
+    eip += sizeof(bug);
+    if ( !is_kernel(eip) ||
+         __copy_from_user(&bug_str, eip, sizeof(bug_str)) ||
+         memcmp(bug_str.mov, BUG_MOV_STR, sizeof(bug_str.mov)) )
+        goto die;
+
+    filename = is_kernel(bug_str.str) ? (char *)bug_str.str : "<unknown>";
+    lineno   = bug.id >> 2;
+
+    if ( id == BUGFRAME_bug )
+    {
+        printk("Xen BUG at %.50s:%d\n", filename, lineno);
         DEBUGGER_trap_fatal(TRAP_invalid_op, regs);
         show_execution_state(regs);
-        panic("FATAL TRAP: vector = %d (invalid opcode)\n", TRAP_invalid_op);
-    }
-
-    if ( (rc = emulate_forced_invalid_op(regs)) != 0 )
-        return rc;
-
-    return do_guest_trap(TRAP_invalid_op, regs, 0);
+        panic("Xen BUG at %.50s:%d\n", filename, lineno);
+    }
+
+    /* ASSERT(): decode the predicate string pointer. */
+    ASSERT(id == BUGFRAME_assert);
+    eip += sizeof(bug_str);
+    if ( !is_kernel(eip) ||
+         __copy_from_user(&bug_str, eip, sizeof(bug_str)) ||
+         memcmp(bug_str.mov, BUG_MOV_STR, sizeof(bug_str.mov)) )
+        goto die;
+
+    predicate = is_kernel(bug_str.str) ? (char *)bug_str.str : "<unknown>";
+    printk("Assertion '%s' failed at %.50s:%d\n",
+           predicate, filename, lineno);
+    DEBUGGER_trap_fatal(TRAP_invalid_op, regs);
+    show_execution_state(regs);
+    panic("Assertion '%s' failed at %.50s:%d\n",
+          predicate, filename, lineno);
+
+ die:
+    DEBUGGER_trap_fatal(TRAP_invalid_op, regs);
+    show_execution_state(regs);
+    panic("FATAL TRAP: vector = %d (invalid opcode)\n", TRAP_invalid_op);
+    return 0;
 }
 
 asmlinkage int do_int3(struct cpu_user_regs *regs)
@@ -877,6 +915,9 @@ static int fixup_page_fault(unsigned lon
         return 0;
     }
 
+    ASSERT(!in_irq());
+    ASSERT(regs->eflags & X86_EFLAGS_IF);
+
     if ( VM_ASSIST(d, VMASST_TYPE_writable_pagetables) &&
          guest_kernel_mode(v, regs) &&
          /* Do not check if access-protection fault since the page may 
@@ -903,8 +944,6 @@ asmlinkage int do_page_fault(struct cpu_
 {
     unsigned long addr, fixup;
     int rc;
-
-    ASSERT(!in_irq());
 
     addr = read_cr2();
 
@@ -1916,6 +1955,8 @@ void unset_nmi_callback(void)
 
 asmlinkage int math_state_restore(struct cpu_user_regs *regs)
 {
+    BUG_ON(!guest_mode(regs));
+
     setup_fpu(current);
 
     if ( current->arch.guest_context.ctrlreg[0] & X86_CR0_TS )
diff -r 9364bea18bc4 -r 202eb735b425 xen/arch/x86/x86_32/entry.S
--- a/xen/arch/x86/x86_32/entry.S       Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/arch/x86/x86_32/entry.S       Thu Feb 22 10:15:29 2007 -0700
@@ -424,7 +424,7 @@ handle_exception:
         testb $X86_EFLAGS_IF>>8,UREGS_eflags+1(%esp)
         jz    exception_with_ints_disabled
         sti                             # re-enable interrupts
-        xorl  %eax,%eax
+1:      xorl  %eax,%eax
         movw  UREGS_entry_vector(%esp),%ax
         movl  %esp,%edx
         pushl %edx                      # push the cpu_user_regs pointer
@@ -451,7 +451,7 @@ exception_with_ints_disabled:
         call  search_pre_exception_table
         addl  $4,%esp
         testl %eax,%eax                 # no fixup code for faulting EIP?
-        jz    FATAL_exception_with_ints_disabled
+        jz    1b
         movl  %eax,UREGS_eip(%esp)
         movl  %esp,%esi
         subl  $4,%esp
diff -r 9364bea18bc4 -r 202eb735b425 xen/arch/x86/x86_64/entry.S
--- a/xen/arch/x86/x86_64/entry.S       Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/arch/x86/x86_64/entry.S       Thu Feb 22 10:15:29 2007 -0700
@@ -362,7 +362,7 @@ ENTRY(handle_exception)
         testb $X86_EFLAGS_IF>>8,UREGS_eflags+1(%rsp)
         jz    exception_with_ints_disabled
         sti
-        movq  %rsp,%rdi
+1:      movq  %rsp,%rdi
         movl  UREGS_entry_vector(%rsp),%eax
         leaq  exception_table(%rip),%rdx
         GET_CURRENT(%rbx)
@@ -388,7 +388,7 @@ exception_with_ints_disabled:
         movq  %rsp,%rdi
         call  search_pre_exception_table
         testq %rax,%rax                 # no fixup code for faulting EIP?
-        jz    FATAL_exception_with_ints_disabled
+        jz    1b
         movq  %rax,UREGS_rip(%rsp)
         subq  $8,UREGS_rsp(%rsp)        # add ec/ev to previous stack frame
         testb $15,UREGS_rsp(%rsp)       # return %rsp is now aligned?
diff -r 9364bea18bc4 -r 202eb735b425 xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c        Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/arch/x86/x86_emulate.c        Thu Feb 22 10:15:29 2007 -0700
@@ -464,10 +464,10 @@ do{ __asm__ __volatile__ (              
 
 #define mode_64bit() (def_ad_bytes == 8)
 
-#define fail_if(p)                              \
-do {                                            \
-    rc = (p) ? X86EMUL_UNHANDLEABLE : 0;        \
-    if ( rc ) goto done;                        \
+#define fail_if(p)                                      \
+do {                                                    \
+    rc = (p) ? X86EMUL_UNHANDLEABLE : X86EMUL_OKAY;     \
+    if ( rc ) goto done;                                \
 } while (0)
 
 /* In future we will be able to generate arbitrary exceptions. */
@@ -726,7 +726,7 @@ x86_emulate(
     uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
     unsigned int op_bytes, def_op_bytes, ad_bytes, def_ad_bytes;
     unsigned int lock_prefix = 0, rep_prefix = 0;
-    int rc = 0;
+    int rc = X86EMUL_OKAY;
     struct operand src, dst;
 
     /* Data operand effective address (usually computed from ModRM). */
@@ -742,7 +742,7 @@ x86_emulate(
     {
         op_bytes = def_op_bytes = 4;
 #ifndef __x86_64__
-        return -1;
+        return X86EMUL_UNHANDLEABLE;
 #endif
     }
 
@@ -1593,7 +1593,7 @@ x86_emulate(
     *ctxt->regs = _regs;
 
  done:
-    return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0;
+    return rc;
 
  special_insn:
     dst.type = OP_NONE;
@@ -2383,5 +2383,5 @@ x86_emulate(
     }
     printk("\n");
 #endif
-    return -1;
+    return X86EMUL_UNHANDLEABLE;
 }
diff -r 9364bea18bc4 -r 202eb735b425 xen/common/domain.c
--- a/xen/common/domain.c       Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/common/domain.c       Thu Feb 22 10:15:29 2007 -0700
@@ -24,13 +24,18 @@
 #include <xen/shutdown.h>
 #include <xen/percpu.h>
 #include <xen/multicall.h>
+#include <xen/rcupdate.h>
 #include <asm/debugger.h>
 #include <public/sched.h>
 #include <public/vcpu.h>
 
-/* Both these structures are protected by the domlist_lock. */
-DEFINE_RWLOCK(domlist_lock);
-struct domain *domain_hash[DOMAIN_HASH_SIZE];
+/* Protect updates/reads (resp.) of domain_list and domain_hash. */
+DEFINE_SPINLOCK(domlist_update_lock);
+DEFINE_RCU_READ_LOCK(domlist_read_lock);
+
+#define DOMAIN_HASH_SIZE 256
+#define DOMAIN_HASH(_id) ((int)(_id)&(DOMAIN_HASH_SIZE-1))
+static struct domain *domain_hash[DOMAIN_HASH_SIZE];
 struct domain *domain_list;
 
 struct domain *dom0;
@@ -174,16 +179,20 @@ struct domain *domain_create(domid_t dom
 
     if ( !is_idle_domain(d) )
     {
-        write_lock(&domlist_lock);
+        spin_lock(&domlist_update_lock);
         pd = &domain_list; /* NB. domain_list maintained in order of domid. */
         for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list )
             if ( (*pd)->domain_id > d->domain_id )
                 break;
         d->next_in_list = *pd;
-        *pd = d;
         d->next_in_hashbucket = domain_hash[DOMAIN_HASH(domid)];
-        domain_hash[DOMAIN_HASH(domid)] = d;
-        write_unlock(&domlist_lock);
+        /* Two rcu assignments are not atomic 
+         * Readers may see inconsistent domlist and hash table
+         * That is OK as long as each RCU reader-side critical section uses
+         * only one or them  */
+        rcu_assign_pointer(*pd, d);
+        rcu_assign_pointer(domain_hash[DOMAIN_HASH(domid)], d);
+        spin_unlock(&domlist_update_lock);
     }
 
     return d;
@@ -207,9 +216,11 @@ struct domain *get_domain_by_id(domid_t 
 {
     struct domain *d;
 
-    read_lock(&domlist_lock);
-    d = domain_hash[DOMAIN_HASH(dom)];
-    while ( d != NULL )
+    rcu_read_lock(&domlist_read_lock);
+
+    for ( d = rcu_dereference(domain_hash[DOMAIN_HASH(dom)]);
+          d != NULL;
+          d = rcu_dereference(d->next_in_hashbucket) )
     {
         if ( d->domain_id == dom )
         {
@@ -217,11 +228,31 @@ struct domain *get_domain_by_id(domid_t 
                 d = NULL;
             break;
         }
-        d = d->next_in_hashbucket;
-    }
-    read_unlock(&domlist_lock);
+    }
+
+    rcu_read_unlock(&domlist_read_lock);
 
     return d;
+}
+
+
+struct domain *find_domain_rcu_lock(domid_t dom)
+{
+    struct domain *d;
+
+    rcu_read_lock(&domlist_read_lock);
+
+    for ( d = rcu_dereference(domain_hash[DOMAIN_HASH(dom)]);
+          d != NULL;
+          d = rcu_dereference(d->next_in_hashbucket) )
+    {
+        if ( d->domain_id == dom )
+            return d;
+    }
+
+    rcu_read_unlock(&domlist_read_lock);
+
+    return NULL;
 }
 
 
@@ -314,6 +345,23 @@ void domain_pause_for_debugger(void)
     send_guest_global_virq(dom0, VIRQ_DEBUGGER);
 }
 
+/* Complete domain destroy after RCU readers are not holding 
+   old references */
+static void complete_domain_destroy(struct rcu_head *head)
+{
+    struct domain *d = container_of(head, struct domain, rcu);
+
+    rangeset_domain_destroy(d);
+
+    evtchn_destroy(d);
+    grant_table_destroy(d);
+
+    arch_domain_destroy(d);
+
+    free_domain(d);
+
+    send_guest_global_virq(dom0, VIRQ_DOM_EXC);
+}
 
 /* Release resources belonging to task @p. */
 void domain_destroy(struct domain *d)
@@ -331,27 +379,19 @@ void domain_destroy(struct domain *d)
         return;
 
     /* Delete from task list and task hashtable. */
-    write_lock(&domlist_lock);
+    spin_lock(&domlist_update_lock);
     pd = &domain_list;
     while ( *pd != d ) 
         pd = &(*pd)->next_in_list;
-    *pd = d->next_in_list;
+    rcu_assign_pointer(*pd, d->next_in_list);
     pd = &domain_hash[DOMAIN_HASH(d->domain_id)];
     while ( *pd != d ) 
         pd = &(*pd)->next_in_hashbucket;
-    *pd = d->next_in_hashbucket;
-    write_unlock(&domlist_lock);
-
-    rangeset_domain_destroy(d);
-
-    evtchn_destroy(d);
-    grant_table_destroy(d);
-
-    arch_domain_destroy(d);
-
-    free_domain(d);
-
-    send_guest_global_virq(dom0, VIRQ_DOM_EXC);
+    rcu_assign_pointer(*pd, d->next_in_hashbucket);
+    spin_unlock(&domlist_update_lock);
+
+    /* schedule RCU asynchronous completion of domain destroy */
+    call_rcu(&d->rcu, complete_domain_destroy);
 }
 
 static void vcpu_pause_setup(struct vcpu *v)
diff -r 9364bea18bc4 -r 202eb735b425 xen/common/domctl.c
--- a/xen/common/domctl.c       Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/common/domctl.c       Thu Feb 22 10:15:29 2007 -0700
@@ -17,6 +17,7 @@
 #include <xen/trace.h>
 #include <xen/console.h>
 #include <xen/iocap.h>
+#include <xen/rcupdate.h>
 #include <xen/guest_access.h>
 #include <xen/bitmap.h>
 #include <asm/current.h>
@@ -140,12 +141,12 @@ static unsigned int default_vcpu0_locati
     cpumask_t      cpu_exclude_map;
 
     /* Do an initial CPU placement. Pick the least-populated CPU. */
-    read_lock(&domlist_lock);
+    rcu_read_lock(&domlist_read_lock);
     for_each_domain ( d )
         for_each_vcpu ( d, v )
         if ( !test_bit(_VCPUF_down, &v->vcpu_flags) )
             cnt[v->processor]++;
-    read_unlock(&domlist_lock);
+    rcu_read_unlock(&domlist_read_lock);
 
     /*
      * If we're on a HT system, we only auto-allocate to a non-primary HT. We 
@@ -480,7 +481,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
         if ( dom == DOMID_SELF )
             dom = current->domain->domain_id;
 
-        read_lock(&domlist_lock);
+        rcu_read_lock(&domlist_read_lock);
 
         for_each_domain ( d )
         {
@@ -490,12 +491,12 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
 
         if ( (d == NULL) || !get_domain(d) )
         {
-            read_unlock(&domlist_lock);
+            rcu_read_unlock(&domlist_read_lock);
             ret = -ESRCH;
             break;
         }
 
-        read_unlock(&domlist_lock);
+        rcu_read_unlock(&domlist_read_lock);
 
         getdomaininfo(d, &op->u.getdomaininfo);
 
diff -r 9364bea18bc4 -r 202eb735b425 xen/common/keyhandler.c
--- a/xen/common/keyhandler.c   Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/common/keyhandler.c   Thu Feb 22 10:15:29 2007 -0700
@@ -145,7 +145,7 @@ static void dump_domains(unsigned char k
     printk("'%c' pressed -> dumping domain info (now=0x%X:%08X)\n", key,
            (u32)(now>>32), (u32)now);
 
-    read_lock(&domlist_lock);
+    rcu_read_lock(&domlist_read_lock);
 
     for_each_domain ( d )
     {
@@ -196,7 +196,7 @@ static void dump_domains(unsigned char k
         }
     }
 
-    read_unlock(&domlist_lock);
+    rcu_read_unlock(&domlist_read_lock);
 }
 
 static cpumask_t read_clocks_cpumask = CPU_MASK_NONE;
diff -r 9364bea18bc4 -r 202eb735b425 xen/common/sched_sedf.c
--- a/xen/common/sched_sedf.c   Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/common/sched_sedf.c   Thu Feb 22 10:15:29 2007 -0700
@@ -1277,6 +1277,7 @@ static void sedf_dump_cpu_state(int i)
     loop = 0;
     printk("\nnot on Q\n");
 
+    rcu_read_lock(&domlist_read_lock);
     for_each_domain ( d )
     {
         for_each_vcpu(d, ed)
@@ -1288,6 +1289,7 @@ static void sedf_dump_cpu_state(int i)
             }
         }
     }
+    rcu_read_unlock(&domlist_read_lock);
 }
 
 
@@ -1298,8 +1300,9 @@ static int sedf_adjust_weights(struct xe
     struct domain      *d;
     int                 sumw[NR_CPUS] = { 0 };
     s_time_t            sumt[NR_CPUS] = { 0 };
- 
+
     /* Sum across all weights. */
+    rcu_read_lock(&domlist_read_lock);
     for_each_domain( d )
     {
         for_each_vcpu( d, p )
@@ -1323,8 +1326,10 @@ static int sedf_adjust_weights(struct xe
             }
         }
     }
+    rcu_read_unlock(&domlist_read_lock);
 
     /* Adjust all slices (and periods) to the new weight. */
+    rcu_read_lock(&domlist_read_lock);
     for_each_domain( d )
     {
         for_each_vcpu ( d, p )
@@ -1341,6 +1346,7 @@ static int sedf_adjust_weights(struct xe
             }
         }
     }
+    rcu_read_unlock(&domlist_read_lock);
 
     return 0;
 }
diff -r 9364bea18bc4 -r 202eb735b425 xen/common/sysctl.c
--- a/xen/common/sysctl.c       Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/common/sysctl.c       Thu Feb 22 10:15:29 2007 -0700
@@ -78,7 +78,7 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysc
         struct xen_domctl_getdomaininfo info;
         u32 num_domains = 0;
 
-        read_lock(&domlist_lock);
+        rcu_read_lock(&domlist_read_lock);
 
         for_each_domain ( d )
         {
@@ -106,7 +106,7 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysc
             num_domains++;
         }
         
-        read_unlock(&domlist_lock);
+        rcu_read_unlock(&domlist_read_lock);
         
         if ( ret != 0 )
             break;
diff -r 9364bea18bc4 -r 202eb735b425 xen/include/asm-x86/bug.h
--- a/xen/include/asm-x86/bug.h Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/include/asm-x86/bug.h Thu Feb 22 10:15:29 2007 -0700
@@ -7,7 +7,15 @@
 #include <asm/x86_32/bug.h>
 #endif
 
-#define BUG()                  __BUG(__FILE__, __LINE__)
-#define dump_execution_state() __BUG(__FILE__, __LINE__ | 0x8000)
+struct bug_frame {
+    unsigned char ud2[2];
+    unsigned char ret;
+    unsigned short id; /* BUGFRAME_??? */
+} __attribute__((packed));
+
+#define BUGFRAME_dump   0
+#define BUGFRAME_bug    1
+#define BUGFRAME_assert 2
+#define BUGFRAME_rsvd   3
 
 #endif /* __X86_BUG_H__ */
diff -r 9364bea18bc4 -r 202eb735b425 xen/include/asm-x86/event.h
--- a/xen/include/asm-x86/event.h       Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/include/asm-x86/event.h       Thu Feb 22 10:15:29 2007 -0700
@@ -10,6 +10,7 @@
 #define __ASM_EVENT_H__
 
 #include <xen/shared.h>
+#include <asm/hvm/irq.h> /* cpu_has_pending_irq() */
 
 static inline void vcpu_kick(struct vcpu *v)
 {
@@ -37,9 +38,9 @@ static inline int local_events_need_deli
 static inline int local_events_need_delivery(void)
 {
     struct vcpu *v = current;
-    /* Note: Bitwise operations result in fast code with no branches. */
-    return (!!vcpu_info(v, evtchn_upcall_pending) &
-             !vcpu_info(v, evtchn_upcall_mask));
+    return ((vcpu_info(v, evtchn_upcall_pending) &&
+             !vcpu_info(v, evtchn_upcall_mask)) ||
+            (is_hvm_vcpu(v) && cpu_has_pending_irq(v)));
 }
 
 static inline int local_event_delivery_is_enabled(void)
diff -r 9364bea18bc4 -r 202eb735b425 xen/include/asm-x86/x86_32/bug.h
--- a/xen/include/asm-x86/x86_32/bug.h  Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/include/asm-x86/x86_32/bug.h  Thu Feb 22 10:15:29 2007 -0700
@@ -1,19 +1,28 @@
 #ifndef __X86_32_BUG_H__
 #define __X86_32_BUG_H__
 
-struct bug_frame {
-    unsigned char ud2[2];
+struct bug_frame_str {
     unsigned char mov[1];
-    unsigned long filename;
-    unsigned char ret;
-    unsigned short line;
+    unsigned long str;
 } __attribute__((packed));
-
 #define BUG_MOV_STR "\xbc"
 
-#define __BUG(file, line)                               \
+#define dump_execution_state()                          \
     asm volatile (                                      \
-        "ud2 ; .byte 0xbc ; .long %c1 ; ret $%c0"       \
-        : : "i" (line), "i" (file) )
+        "ud2 ; ret $%c0"                                \
+        : : "i" (BUGFRAME_dump) )
+
+#define BUG()                                           \
+    asm volatile (                                      \
+        "ud2 ; ret $%c0 ; .byte 0xbc ; .long %c1"       \
+        : : "i" (BUGFRAME_bug | (__LINE__<<2)),         \
+            "i" (__FILE__) )
+
+#define assert_failed(p)                                \
+    asm volatile (                                      \
+        "ud2 ; ret $%c0 ; .byte 0xbc ; .long %c1"       \
+        " ; .byte 0xbc ; .long %c2"                     \
+        : : "i" (BUGFRAME_assert | (__LINE__<<2)),      \
+            "i" (__FILE__), "i" (#p) )
 
 #endif /* __X86_32_BUG_H__ */
diff -r 9364bea18bc4 -r 202eb735b425 xen/include/asm-x86/x86_64/bug.h
--- a/xen/include/asm-x86/x86_64/bug.h  Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/include/asm-x86/x86_64/bug.h  Thu Feb 22 10:15:29 2007 -0700
@@ -1,19 +1,28 @@
 #ifndef __X86_64_BUG_H__
 #define __X86_64_BUG_H__
 
-struct bug_frame {
-    unsigned char ud2[2];
+struct bug_frame_str {
     unsigned char mov[2];
-    unsigned long filename;
-    unsigned char ret;
-    unsigned short line;
+    unsigned long str;
 } __attribute__((packed));
-
 #define BUG_MOV_STR "\x48\xbc"
 
-#define __BUG(file, line)                               \
+#define dump_execution_state()                          \
     asm volatile (                                      \
-        "ud2 ; .byte 0x48,0xbc ; .quad %c1 ; ret $%c0"  \
-        : : "i" (line), "i" (file) )
+        "ud2 ; ret $%c0"                                \
+        : : "i" (BUGFRAME_dump) )
+
+#define BUG()                                           \
+    asm volatile (                                      \
+        "ud2 ; ret $%c0 ; .byte 0x48,0xbc ; .quad %c1"  \
+        : : "i" (BUGFRAME_bug | (__LINE__<<2)),         \
+            "i" (__FILE__) )
+
+#define assert_failed(p)                                \
+    asm volatile (                                      \
+        "ud2 ; ret $%c0 ; .byte 0x48,0xbc ; .quad %c1"  \
+        " ; .byte 0x48,0xbc ; .quad %c2"                \
+        : : "i" (BUGFRAME_assert | (__LINE__<<2)),      \
+            "i" (__FILE__), "i" (#p) )
 
 #endif /* __X86_64_BUG_H__ */
diff -r 9364bea18bc4 -r 202eb735b425 xen/include/asm-x86/x86_emulate.h
--- a/xen/include/asm-x86/x86_emulate.h Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/include/asm-x86/x86_emulate.h Thu Feb 22 10:15:29 2007 -0700
@@ -46,26 +46,32 @@ enum x86_segment {
 };
 
 /*
+ * Return codes from state-accessor functions and from x86_emulate().
+ */
+ /* Completed successfully. State modified appropriately. */
+#define X86EMUL_OKAY           0
+ /* Unhandleable access or emulation. No state modified. */
+#define X86EMUL_UNHANDLEABLE   1
+ /* Exception raised and requires delivery. */
+#define X86EMUL_EXCEPTION      2
+ /* Retry the emulation for some reason. No state modified. */
+#define X86EMUL_RETRY          3
+ /* (cmpxchg accessor): CMPXCHG failed. Maps to X86EMUL_RETRY in caller. */
+#define X86EMUL_CMPXCHG_FAILED 3
+
+/*
  * These operations represent the instruction emulator's interface to memory.
  * 
  * NOTES:
  *  1. If the access fails (cannot emulate, or a standard access faults) then
  *     it is up to the memop to propagate the fault to the guest VM via
  *     some out-of-band mechanism, unknown to the emulator. The memop signals
- *     failure by returning X86EMUL_PROPAGATE_FAULT to the emulator, which will
+ *     failure by returning X86EMUL_EXCEPTION to the emulator, which will
  *     then immediately bail.
  *  2. Valid access sizes are 1, 2, 4 and 8 bytes. On x86/32 systems only
  *     cmpxchg8b_emulated need support 8-byte accesses.
  *  3. The emulator cannot handle 64-bit mode emulation on an x86/32 system.
  */
-/* Access completed successfully: continue emulation as normal. */
-#define X86EMUL_CONTINUE        0
-/* Access is unhandleable: bail from emulation and return error to caller. */
-#define X86EMUL_UNHANDLEABLE    1
-/* Terminate emulation but return success to the caller. */
-#define X86EMUL_PROPAGATE_FAULT 2 /* propagate a generated fault to guest */
-#define X86EMUL_RETRY_INSTR     2 /* retry the instruction for some reason */
-#define X86EMUL_CMPXCHG_FAILED  2 /* cmpxchg did not see expected value */
 struct x86_emulate_ops
 {
     /*
diff -r 9364bea18bc4 -r 202eb735b425 xen/include/xen/lib.h
--- a/xen/include/xen/lib.h     Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/include/xen/lib.h     Thu Feb 22 10:15:29 2007 -0700
@@ -16,18 +16,20 @@ void __bug(char *file, int line) __attri
 /* Force a compilation error if condition is true */
 #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2 * !!(condition)]))
 
+#ifndef assert_failed
+#define assert_failed(p)                                        \
+do {                                                            \
+    printk("Assertion '%s' failed, line %d, file %s\n", #p ,    \
+                   __LINE__, __FILE__);                         \
+    BUG();                                                      \
+} while (0)
+#endif
+
 #ifndef NDEBUG
-#define ASSERT(_p)                                                      \
-    do {                                                                \
-        if ( unlikely(!(_p)) )                                          \
-        {                                                               \
-            printk("Assertion '%s' failed, line %d, file %s\n", #_p ,   \
-                   __LINE__, __FILE__);                                 \
-            BUG();                                                      \
-        }                                                               \
-    } while ( 0 )
+#define ASSERT(p) \
+    do { if ( unlikely(!(p)) ) assert_failed(p); } while (0)
 #else
-#define ASSERT(_p) ((void)0)
+#define ASSERT(p) ((void)0)
 #endif
 
 #define SWAP(_a, _b) \
diff -r 9364bea18bc4 -r 202eb735b425 xen/include/xen/rcupdate.h
--- a/xen/include/xen/rcupdate.h        Thu Feb 22 09:42:13 2007 -0700
+++ b/xen/include/xen/rcupdate.h        Thu Feb 22 10:15:29 2007 -0700
@@ -111,6 +111,59 @@ int rcu_pending(int cpu);
 int rcu_pending(int cpu);
 int rcu_needs_cpu(int cpu);
 
+/*
+ * Dummy lock type for passing to rcu_read_{lock,unlock}. Currently exists
+ * only to document the reason for rcu_read_lock() critical sections.
+ */
+struct _rcu_read_lock {};
+typedef struct _rcu_read_lock rcu_read_lock_t;
+#define DEFINE_RCU_READ_LOCK(x) rcu_read_lock_t x
+
+/**
+ * rcu_read_lock - mark the beginning of an RCU read-side critical section.
+ *
+ * When call_rcu() is invoked
+ * on one CPU while other CPUs are within RCU read-side critical
+ * sections, invocation of the corresponding RCU callback is deferred
+ * until after the all the other CPUs exit their critical sections.
+ *
+ * Note, however, that RCU callbacks are permitted to run concurrently
+ * with RCU read-side critical sections.  One way that this can happen
+ * is via the following sequence of events: (1) CPU 0 enters an RCU
+ * read-side critical section, (2) CPU 1 invokes call_rcu() to register
+ * an RCU callback, (3) CPU 0 exits the RCU read-side critical section,
+ * (4) CPU 2 enters a RCU read-side critical section, (5) the RCU

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog