[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.