diff --git a/docs/devhelp/libvirt-libvirt.html b/docs/devhelp/libvirt-libvirt.html
index be5eb44..0696a02 100644
--- a/docs/devhelp/libvirt-libvirt.html
+++ b/docs/devhelp/libvirt-libvirt.html
@@ -261,6 +261,7 @@ const char *	<a href="#virNodeDeviceGetParent">virNodeDeviceGetParent</a>	(<a hr
 <a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a>	<a href="#virConnectOpen">virConnectOpen</a>		(const char * name);
 <a href="libvirt-libvirt.html#virDomainPtr">virDomainPtr</a>	<a href="#virDomainCreateXML">virDomainCreateXML</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br/>					 const char * xmlDesc, <br/>					 unsigned int flags);
 int	<a href="#virNodeDeviceRef">virNodeDeviceRef</a>		(<a href="libvirt-libvirt.html#virNodeDevicePtr">virNodeDevicePtr</a> dev);
+<a href="libvirt-libvirt.html#virStorageVolPtr">virStorageVolPtr</a>	<a href="#virStorageVolClone">virStorageVolClone</a>	(<a href="libvirt-libvirt.html#virStorageVolPtr">virStorageVolPtr</a> vol, <br/>						 const char * xmldesc, <br/>						 unsigned int flags);
 int	<a href="#virDomainSetVcpus">virDomainSetVcpus</a>		(<a href="libvirt-libvirt.html#virDomainPtr">virDomainPtr</a> domain, <br/>					 unsigned int nvcpus);
 int	<a href="#virDomainRef">virDomainRef</a>			(<a href="libvirt-libvirt.html#virDomainPtr">virDomainPtr</a> domain);
 int	<a href="#virConnectDomainEventRegister">virConnectDomainEventRegister</a>	(<a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a> conn, <br/>					 <a href="libvirt-libvirt.html#virConnectDomainEventCallback">virConnectDomainEventCallback</a> cb, <br/>					 void * opaque, <br/>					 <a href="libvirt-libvirt.html#virFreeCallback">virFreeCallback</a> freecb);
@@ -1320,6 +1321,10 @@ The content of this structure is not made public by the API.
 </pre><p>Undefine an inactive storage pool</p>
 <div class="variablelist"><table border="0"><col align="left"/><tbody><tr><td><span class="term"><i><tt>pool</tt></i>:</span></td><td>pointer to storage pool</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>a <a href="libvirt-libvirt.html#virStoragePoolPtr">virStoragePoolPtr</a> object, or NULL if creation failed</td></tr></tbody></table></div></div>
         <hr/>
+        <div class="refsect2" lang="en"><h3><a name="virStorageVolClone"/>virStorageVolClone ()</h3><pre class="programlisting"><a href="libvirt-libvirt.html#virStorageVolPtr">virStorageVolPtr</a>	virStorageVolClone	(<a href="libvirt-libvirt.html#virStorageVolPtr">virStorageVolPtr</a> vol, <br/>						 const char * xmldesc, <br/>						 unsigned int flags)<br/>
+</pre><p>Clone a storage volume within the parent pool. Information for the new volume (name, perms) are passed via a typical volume XML description Not all pools support cloning of volumes</p>
+<div class="variablelist"><table border="0"><col align="left"/><tbody><tr><td><span class="term"><i><tt>vol</tt></i>:</span></td><td>pointer to storage vol to clone</td></tr><tr><td><span class="term"><i><tt>xmldesc</tt></i>:</span></td><td>description of volume to create</td></tr><tr><td><span class="term"><i><tt>flags</tt></i>:</span></td><td>flags for creation (unused, pass 0)</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>the storage volume, or NULL on error</td></tr></tbody></table></div></div>
+        <hr/>
         <div class="refsect2" lang="en"><h3><a name="virStorageVolCreateXML"/>virStorageVolCreateXML ()</h3><pre class="programlisting"><a href="libvirt-libvirt.html#virStorageVolPtr">virStorageVolPtr</a>	virStorageVolCreateXML	(<a href="libvirt-libvirt.html#virStoragePoolPtr">virStoragePoolPtr</a> pool, <br/>						 const char * xmldesc, <br/>						 unsigned int flags)<br/>
 </pre><p>Create a storage volume within a pool based on an XML description. Not all pools support creation of volumes</p>
 <div class="variablelist"><table border="0"><col align="left"/><tbody><tr><td><span class="term"><i><tt>pool</tt></i>:</span></td><td>pointer to storage pool</td></tr><tr><td><span class="term"><i><tt>xmldesc</tt></i>:</span></td><td>description of volume to create</td></tr><tr><td><span class="term"><i><tt>flags</tt></i>:</span></td><td>flags for creation (unused, pass 0)</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>the storage volume, or NULL on error</td></tr></tbody></table></div></div>
diff --git a/docs/html/libvirt-libvirt.html b/docs/html/libvirt-libvirt.html
index f2c9a5d..2766de1 100644
--- a/docs/html/libvirt-libvirt.html
+++ b/docs/html/libvirt-libvirt.html
@@ -243,6 +243,7 @@ int	<a href="#virStoragePoolRef">virStoragePoolRef</a>		(<a href="libvirt-libvir
 int	<a href="#virStoragePoolRefresh">virStoragePoolRefresh</a>		(<a href="libvirt-libvirt.html#virStoragePoolPtr">virStoragePoolPtr</a> pool, <br />					 unsigned int flags)
 int	<a href="#virStoragePoolSetAutostart">virStoragePoolSetAutostart</a>	(<a href="libvirt-libvirt.html#virStoragePoolPtr">virStoragePoolPtr</a> pool, <br />					 int autostart)
 int	<a href="#virStoragePoolUndefine">virStoragePoolUndefine</a>		(<a href="libvirt-libvirt.html#virStoragePoolPtr">virStoragePoolPtr</a> pool)
+<a href="libvirt-libvirt.html#virStorageVolPtr">virStorageVolPtr</a>	<a href="#virStorageVolClone">virStorageVolClone</a>	(<a href="libvirt-libvirt.html#virStorageVolPtr">virStorageVolPtr</a> vol, <br />						 const char * xmldesc, <br />						 unsigned int flags)
 <a href="libvirt-libvirt.html#virStorageVolPtr">virStorageVolPtr</a>	<a href="#virStorageVolCreateXML">virStorageVolCreateXML</a>	(<a href="libvirt-libvirt.html#virStoragePoolPtr">virStoragePoolPtr</a> pool, <br />						 const char * xmldesc, <br />						 unsigned int flags)
 int	<a href="#virStorageVolDelete">virStorageVolDelete</a>		(<a href="libvirt-libvirt.html#virStorageVolPtr">virStorageVolPtr</a> vol, <br />					 unsigned int flags)
 int	<a href="#virStorageVolFree">virStorageVolFree</a>		(<a href="libvirt-libvirt.html#virStorageVolPtr">virStorageVolPtr</a> vol)
@@ -500,7 +501,8 @@ int	<a href="#virStorageVolRef">virStorageVolRef</a>		(<a href="libvirt-libvirt.
 </pre><p>Increment the reference count on the pool. For each additional call to this method, there shall be a corresponding call to <a href="libvirt-libvirt.html#virStoragePoolFree">virStoragePoolFree</a> to release the reference count, once the caller no longer needs the reference to this object. This method is typically useful for applications where multiple threads are using a connection, and it is required that the connection remain open until all threads have finished using it. ie, each new thread using a pool would increment the reference count.</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>pool</tt></i>:</span></td><td></td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td></td></tr></tbody></table></div><h3><a name="virStoragePoolRefresh" id="virStoragePoolRefresh"><code>virStoragePoolRefresh</code></a></h3><pre class="programlisting">int	virStoragePoolRefresh		(<a href="libvirt-libvirt.html#virStoragePoolPtr">virStoragePoolPtr</a> pool, <br />					 unsigned int flags)<br />
 </pre><p>Request that the pool refresh its list of volumes. This may involve communicating with a remote server, and/or initializing new devices at the OS layer</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>pool</tt></i>:</span></td><td>pointer to storage pool</td></tr><tr><td><span class="term"><i><tt>flags</tt></i>:</span></td><td>flags to control refresh behaviour (currently unused, use 0)</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>0 if the volume list was refreshed, -1 on failure</td></tr></tbody></table></div><h3><a name="virStoragePoolSetAutostart" id="virStoragePoolSetAutostart"><code>virStoragePoolSetAutostart</code></a></h3><pre class="programlisting">int	virStoragePoolSetAutostart	(<a href="libvirt-libvirt.html#virStoragePoolPtr">virStoragePoolPtr</a> pool, <br />					 int autostart)<br />
 </pre><p>Sets the autostart flag</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>pool</tt></i>:</span></td><td>pointer to storage pool</td></tr><tr><td><span class="term"><i><tt>autostart</tt></i>:</span></td><td>new flag setting</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>0 on success, -1 on failure</td></tr></tbody></table></div><h3><a name="virStoragePoolUndefine" id="virStoragePoolUndefine"><code>virStoragePoolUndefine</code></a></h3><pre class="programlisting">int	virStoragePoolUndefine		(<a href="libvirt-libvirt.html#virStoragePoolPtr">virStoragePoolPtr</a> pool)<br />
-</pre><p>Undefine an inactive storage pool</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>pool</tt></i>:</span></td><td>pointer to storage pool</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>a <a href="libvirt-libvirt.html#virStoragePoolPtr">virStoragePoolPtr</a> object, or NULL if creation failed</td></tr></tbody></table></div><h3><a name="virStorageVolCreateXML" id="virStorageVolCreateXML"><code>virStorageVolCreateXML</code></a></h3><pre class="programlisting"><a href="libvirt-libvirt.html#virStorageVolPtr">virStorageVolPtr</a>	virStorageVolCreateXML	(<a href="libvirt-libvirt.html#virStoragePoolPtr">virStoragePoolPtr</a> pool, <br />						 const char * xmldesc, <br />						 unsigned int flags)<br />
+</pre><p>Undefine an inactive storage pool</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>pool</tt></i>:</span></td><td>pointer to storage pool</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>a <a href="libvirt-libvirt.html#virStoragePoolPtr">virStoragePoolPtr</a> object, or NULL if creation failed</td></tr></tbody></table></div><h3><a name="virStorageVolClone" id="virStorageVolClone"><code>virStorageVolClone</code></a></h3><pre class="programlisting"><a href="libvirt-libvirt.html#virStorageVolPtr">virStorageVolPtr</a>	virStorageVolClone	(<a href="libvirt-libvirt.html#virStorageVolPtr">virStorageVolPtr</a> vol, <br />						 const char * xmldesc, <br />						 unsigned int flags)<br />
+</pre><p>Clone a storage volume within the parent pool. Information for the new volume (name, perms) are passed via a typical volume XML description Not all pools support cloning of volumes</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>vol</tt></i>:</span></td><td>pointer to storage vol to clone</td></tr><tr><td><span class="term"><i><tt>xmldesc</tt></i>:</span></td><td>description of volume to create</td></tr><tr><td><span class="term"><i><tt>flags</tt></i>:</span></td><td>flags for creation (unused, pass 0)</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>the storage volume, or NULL on error</td></tr></tbody></table></div><h3><a name="virStorageVolCreateXML" id="virStorageVolCreateXML"><code>virStorageVolCreateXML</code></a></h3><pre class="programlisting"><a href="libvirt-libvirt.html#virStorageVolPtr">virStorageVolPtr</a>	virStorageVolCreateXML	(<a href="libvirt-libvirt.html#virStoragePoolPtr">virStoragePoolPtr</a> pool, <br />						 const char * xmldesc, <br />						 unsigned int flags)<br />
 </pre><p>Create a storage volume within a pool based on an XML description. Not all pools support creation of volumes</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>pool</tt></i>:</span></td><td>pointer to storage pool</td></tr><tr><td><span class="term"><i><tt>xmldesc</tt></i>:</span></td><td>description of volume to create</td></tr><tr><td><span class="term"><i><tt>flags</tt></i>:</span></td><td>flags for creation (unused, pass 0)</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>the storage volume, or NULL on error</td></tr></tbody></table></div><h3><a name="virStorageVolDelete" id="virStorageVolDelete"><code>virStorageVolDelete</code></a></h3><pre class="programlisting">int	virStorageVolDelete		(<a href="libvirt-libvirt.html#virStorageVolPtr">virStorageVolPtr</a> vol, <br />					 unsigned int flags)<br />
 </pre><p>Delete the storage volume from the pool</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>vol</tt></i>:</span></td><td>pointer to storage volume</td></tr><tr><td><span class="term"><i><tt>flags</tt></i>:</span></td><td>future flags, use 0 for now</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>0 on success, or -1 on error</td></tr></tbody></table></div><h3><a name="virStorageVolFree" id="virStorageVolFree"><code>virStorageVolFree</code></a></h3><pre class="programlisting">int	virStorageVolFree		(<a href="libvirt-libvirt.html#virStorageVolPtr">virStorageVolPtr</a> vol)<br />
 </pre><p>Release the storage volume handle. The underlying storage volume continues to exist.</p><div class="variablelist"><table border="0"><col align="left" /><tbody><tr><td><span class="term"><i><tt>vol</tt></i>:</span></td><td>pointer to storage volume</td></tr><tr><td><span class="term"><i><tt>Returns</tt></i>:</span></td><td>0 on success, or -1 on error</td></tr></tbody></table></div><h3><a name="virStorageVolGetConnect" id="virStorageVolGetConnect"><code>virStorageVolGetConnect</code></a></h3><pre class="programlisting"><a href="libvirt-libvirt.html#virConnectPtr">virConnectPtr</a>	virStorageVolGetConnect	(<a href="libvirt-libvirt.html#virStorageVolPtr">virStorageVolPtr</a> vol)<br />
diff --git a/docs/libvirt-api.xml b/docs/libvirt-api.xml
index 81bfbda..0e586e5 100644
--- a/docs/libvirt-api.xml
+++ b/docs/libvirt-api.xml
@@ -311,6 +311,7 @@
      <exports symbol='virConnectOpen' type='function'/>
      <exports symbol='virDomainCreateXML' type='function'/>
      <exports symbol='virNodeDeviceRef' type='function'/>
+     <exports symbol='virStorageVolClone' type='function'/>
      <exports symbol='virDomainSetVcpus' type='function'/>
      <exports symbol='virDomainRef' type='function'/>
      <exports symbol='virConnectDomainEventRegister' type='function'/>
@@ -1753,6 +1754,13 @@ see note above'/>
       <return type='int' info='a virStoragePoolPtr object, or NULL if creation failed'/>
       <arg name='pool' type='virStoragePoolPtr' info='pointer to storage pool'/>
     </function>
+    <function name='virStorageVolClone' file='libvirt' module='libvirt'>
+      <info>Clone a storage volume within the parent pool. Information for the new volume (name, perms) are passed via a typical volume XML description Not all pools support cloning of volumes</info>
+      <return type='virStorageVolPtr' info='the storage volume, or NULL on error'/>
+      <arg name='vol' type='virStorageVolPtr' info='pointer to storage vol to clone'/>
+      <arg name='xmldesc' type='const char *' info='description of volume to create'/>
+      <arg name='flags' type='unsigned int' info='flags for creation (unused, pass 0)'/>
+    </function>
     <function name='virStorageVolCreateXML' file='libvirt' module='libvirt'>
       <info>Create a storage volume within a pool based on an XML description. Not all pools support creation of volumes</info>
       <return type='virStorageVolPtr' info='the storage volume, or NULL on error'/>
diff --git a/docs/libvirt-refs.xml b/docs/libvirt-refs.xml
index 86ffb46..f66a19c 100644
--- a/docs/libvirt-refs.xml
+++ b/docs/libvirt-refs.xml
@@ -396,6 +396,7 @@
     <reference name='virStoragePoolState' href='html/libvirt-libvirt.html#virStoragePoolState'/>
     <reference name='virStoragePoolUndefine' href='html/libvirt-libvirt.html#virStoragePoolUndefine'/>
     <reference name='virStorageVol' href='html/libvirt-libvirt.html#virStorageVol'/>
+    <reference name='virStorageVolClone' href='html/libvirt-libvirt.html#virStorageVolClone'/>
     <reference name='virStorageVolCreateXML' href='html/libvirt-libvirt.html#virStorageVolCreateXML'/>
     <reference name='virStorageVolDelete' href='html/libvirt-libvirt.html#virStorageVolDelete'/>
     <reference name='virStorageVolDeleteFlags' href='html/libvirt-libvirt.html#virStorageVolDeleteFlags'/>
@@ -821,6 +822,7 @@
       <ref name='virStoragePoolState'/>
       <ref name='virStoragePoolUndefine'/>
       <ref name='virStorageVol'/>
+      <ref name='virStorageVolClone'/>
       <ref name='virStorageVolCreateXML'/>
       <ref name='virStorageVolDelete'/>
       <ref name='virStorageVolDeleteFlags'/>
@@ -897,6 +899,7 @@
       <ref name='virStoragePoolLookupByVolume'/>
     </type>
     <type name='virStorageVolPtr'>
+      <ref name='virStorageVolClone'/>
       <ref name='virStorageVolCreateXML'/>
       <ref name='virStorageVolLookupByKey'/>
       <ref name='virStorageVolLookupByName'/>
@@ -960,6 +963,7 @@
       <ref name='virStoragePoolDelete'/>
       <ref name='virStoragePoolGetXMLDesc'/>
       <ref name='virStoragePoolRefresh'/>
+      <ref name='virStorageVolClone'/>
       <ref name='virStorageVolCreateXML'/>
       <ref name='virStorageVolDelete'/>
       <ref name='virStorageVolGetXMLDesc'/>
@@ -1210,6 +1214,7 @@
     </type>
     <type name='virStorageVolPtr'>
       <ref name='virStoragePoolLookupByVolume'/>
+      <ref name='virStorageVolClone'/>
       <ref name='virStorageVolDelete'/>
       <ref name='virStorageVolFree'/>
       <ref name='virStorageVolGetConnect'/>
@@ -1534,6 +1539,7 @@
       <ref name='virStoragePoolState'/>
       <ref name='virStoragePoolUndefine'/>
       <ref name='virStorageVol'/>
+      <ref name='virStorageVolClone'/>
       <ref name='virStorageVolCreateXML'/>
       <ref name='virStorageVolDelete'/>
       <ref name='virStorageVolDeleteFlags'/>
@@ -1759,6 +1765,9 @@
         <word name='Change'>
           <ref name='virDomainSetSchedulerParameters'/>
         </word>
+        <word name='Clone'>
+          <ref name='virStorageVolClone'/>
+        </word>
         <word name='Collect'>
           <ref name='virConnectListDomains'/>
           <ref name='virConnectListNetworks'/>
@@ -1972,6 +1981,9 @@
           <ref name='virDomainBlockStats'/>
           <ref name='virDomainInterfaceStats'/>
         </word>
+        <word name='Information'>
+          <ref name='virStorageVolClone'/>
+        </word>
         <word name='Initialize'>
           <ref name='virInitialize'/>
         </word>
@@ -2025,6 +2037,8 @@
           <ref name='virNodeDeviceLookupByName'/>
         </word>
       </letter>
+    </chunk>
+    <chunk name='chunk1'>
       <letter name='M'>
         <word name='Macro'>
           <ref name='LIBVIR_VERSION_NUMBER'/>
@@ -2049,8 +2063,6 @@
           <ref name='virDomainMigrate'/>
         </word>
       </letter>
-    </chunk>
-    <chunk name='chunk1'>
       <letter name='N'>
         <word name='NFS'>
           <ref name='VIR_SECURITY_LABEL_BUFLEN'/>
@@ -2070,6 +2082,7 @@
           <ref name='virConnectGetURI'/>
         </word>
         <word name='Not'>
+          <ref name='virStorageVolClone'/>
           <ref name='virStorageVolCreateXML'/>
         </word>
         <word name='Note'>
@@ -2381,26 +2394,6 @@
         </word>
       </letter>
       <letter name='X'>
-        <word name='XML'>
-          <ref name='virConnectFindStoragePoolSources'/>
-          <ref name='virConnectGetCapabilities'/>
-          <ref name='virConnectGetMaxVcpus'/>
-          <ref name='virDomainAttachDevice'/>
-          <ref name='virDomainCreateLinux'/>
-          <ref name='virDomainCreateXML'/>
-          <ref name='virDomainDefineXML'/>
-          <ref name='virDomainDetachDevice'/>
-          <ref name='virDomainGetXMLDesc'/>
-          <ref name='virNetworkCreateXML'/>
-          <ref name='virNetworkDefineXML'/>
-          <ref name='virNetworkGetXMLDesc'/>
-          <ref name='virNodeDeviceGetXMLDesc'/>
-          <ref name='virStoragePoolCreateXML'/>
-          <ref name='virStoragePoolDefineXML'/>
-          <ref name='virStoragePoolGetXMLDesc'/>
-          <ref name='virStorageVolCreateXML'/>
-          <ref name='virStorageVolGetXMLDesc'/>
-        </word>
         <word name='Xen'>
           <ref name='_virDomainBlockStats'/>
           <ref name='virDomainCoreDump'/>
@@ -2526,6 +2519,7 @@
           <ref name='virStoragePoolFree'/>
           <ref name='virStoragePoolGetXMLDesc'/>
           <ref name='virStoragePoolRef'/>
+          <ref name='virStorageVolClone'/>
           <ref name='virStorageVolCreateXML'/>
           <ref name='virStorageVolGetXMLDesc'/>
           <ref name='virStorageVolRef'/>
@@ -2646,6 +2640,7 @@
           <ref name='virNodeDeviceReset'/>
           <ref name='virSetErrorFunc'/>
           <ref name='virStoragePoolRef'/>
+          <ref name='virStorageVolClone'/>
           <ref name='virStorageVolRef'/>
         </word>
         <word name='area'>
@@ -3027,6 +3022,12 @@
         <word name='client'>
           <ref name='virConnectGetCapabilities'/>
         </word>
+        <word name='clone'>
+          <ref name='virStorageVolClone'/>
+        </word>
+        <word name='cloning'>
+          <ref name='virStorageVolClone'/>
+        </word>
         <word name='closes'>
           <ref name='virConnectClose'/>
         </word>
@@ -3207,12 +3208,14 @@
         </word>
         <word name='create'>
           <ref name='virNetworkDefineXML'/>
+          <ref name='virStorageVolClone'/>
           <ref name='virStorageVolCreateXML'/>
         </word>
         <word name='creation'>
           <ref name='virStoragePoolCreateXML'/>
           <ref name='virStoragePoolDefineXML'/>
           <ref name='virStoragePoolUndefine'/>
+          <ref name='virStorageVolClone'/>
           <ref name='virStorageVolCreateXML'/>
         </word>
         <word name='credentials'>
@@ -3323,6 +3326,7 @@
           <ref name='virNetworkGetXMLDesc'/>
           <ref name='virStoragePoolCreateXML'/>
           <ref name='virStoragePoolDefineXML'/>
+          <ref name='virStorageVolClone'/>
           <ref name='virStorageVolCreateXML'/>
         </word>
         <word name='descriptor'>
@@ -3727,6 +3731,7 @@
           <ref name='virStoragePoolDelete'/>
           <ref name='virStoragePoolGetXMLDesc'/>
           <ref name='virStoragePoolRefresh'/>
+          <ref name='virStorageVolClone'/>
           <ref name='virStorageVolCreateXML'/>
           <ref name='virStorageVolDelete'/>
           <ref name='virStorageVolGetXMLDesc'/>
@@ -4956,6 +4961,7 @@
         </word>
         <word name='parent'>
           <ref name='virNodeDeviceGetParent'/>
+          <ref name='virStorageVolClone'/>
         </word>
         <word name='part'>
           <ref name='_virError'/>
@@ -4981,12 +4987,14 @@
           <ref name='virNodeDeviceGetXMLDesc'/>
           <ref name='virNodeListDevices'/>
           <ref name='virNodeNumOfDevices'/>
+          <ref name='virStorageVolClone'/>
           <ref name='virStorageVolCreateXML'/>
           <ref name='virStorageVolGetXMLDesc'/>
         </word>
         <word name='passed'>
           <ref name='virConnectDomainEventRegister'/>
           <ref name='virConnectGetURI'/>
+          <ref name='virStorageVolClone'/>
         </word>
         <word name='path'>
           <ref name='virDomainBlockPeek'/>
@@ -4996,6 +5004,7 @@
           <ref name='virDomainMigrate'/>
           <ref name='virDomainRestore'/>
           <ref name='virDomainSave'/>
+          <ref name='virStorageVolClone'/>
           <ref name='virStorageVolGetPath'/>
           <ref name='virStorageVolLookupByPath'/>
         </word>
@@ -5056,6 +5065,7 @@
           <ref name='virDomainCreate'/>
           <ref name='virNetworkCreate'/>
           <ref name='virStoragePoolNumOfVolumes'/>
+          <ref name='virStorageVolClone'/>
           <ref name='virStorageVolCreateXML'/>
         </word>
         <word name='port'>
@@ -5814,6 +5824,7 @@
           <ref name='virDomainInterfaceStats'/>
           <ref name='virDomainMigrate'/>
           <ref name='virDomainSetVcpus'/>
+          <ref name='virStorageVolClone'/>
           <ref name='virStorageVolCreateXML'/>
         </word>
         <word name='supported'>
@@ -6024,6 +6035,9 @@
           <ref name='virConnectFindStoragePoolSources'/>
           <ref name='virDomainMigrate'/>
         </word>
+        <word name='typical'>
+          <ref name='virStorageVolClone'/>
+        </word>
         <word name='typically'>
           <ref name='virConnectRef'/>
           <ref name='virDomainMigrate'/>
@@ -6099,6 +6113,7 @@
           <ref name='virNodeListDevices'/>
           <ref name='virNodeNumOfDevices'/>
           <ref name='virStoragePoolRefresh'/>
+          <ref name='virStorageVolClone'/>
           <ref name='virStorageVolCreateXML'/>
           <ref name='virStorageVolGetXMLDesc'/>
         </word>
@@ -6272,6 +6287,7 @@
         </word>
         <word name='via'>
           <ref name='virConnectOpenAuth'/>
+          <ref name='virStorageVolClone'/>
         </word>
         <word name='virConnect'>
           <ref name='virConnectDomainEventCallback'/>
@@ -6491,6 +6507,7 @@
           <ref name='virDomainSetVcpus'/>
         </word>
         <word name='vol'>
+          <ref name='virStorageVolClone'/>
           <ref name='virStorageVolRef'/>
         </word>
         <word name='volatile'>
@@ -6500,6 +6517,7 @@
         <word name='volumes'>
           <ref name='virStoragePoolNumOfVolumes'/>
           <ref name='virStoragePoolRefresh'/>
+          <ref name='virStorageVolClone'/>
           <ref name='virStorageVolCreateXML'/>
         </word>
       </letter>
@@ -6584,6 +6602,7 @@
           <ref name='virDomainBlockStats'/>
           <ref name='virDomainInterfaceStats'/>
           <ref name='virStoragePoolNumOfVolumes'/>
+          <ref name='virStorageVolClone'/>
           <ref name='virStorageVolCreateXML'/>
           <ref name='virStorageVolGetName'/>
           <ref name='virStorageVolLookupByName'/>
@@ -6671,8 +6690,8 @@
       </letter>
     </chunk>
     <chunks>
-      <chunk name='chunk0' start='A' end='M'/>
-      <chunk name='chunk1' start='N' end='a'/>
+      <chunk name='chunk0' start='A' end='L'/>
+      <chunk name='chunk1' start='M' end='a'/>
       <chunk name='chunk2' start='b' end='c'/>
       <chunk name='chunk3' start='d' end='e'/>
       <chunk name='chunk4' start='f' end='g'/>
diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h
index bd94a18..2612b10 100644
--- a/include/libvirt/libvirt.h
+++ b/include/libvirt/libvirt.h
@@ -1047,6 +1047,9 @@ const char*             virStorageVolGetKey             (virStorageVolPtr vol);
 virStorageVolPtr        virStorageVolCreateXML          (virStoragePoolPtr pool,
                                                          const char *xmldesc,
                                                          unsigned int flags);
+virStorageVolPtr        virStorageVolClone              (virStorageVolPtr vol,
+                                                         const char *xmldesc,
+                                                         unsigned int flags);
 int                     virStorageVolDelete             (virStorageVolPtr vol,
                                                          unsigned int flags);
 int                     virStorageVolRef                (virStorageVolPtr vol);
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index a028b21..0f4dd27 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1047,6 +1047,9 @@ const char*             virStorageVolGetKey             (virStorageVolPtr vol);
 virStorageVolPtr        virStorageVolCreateXML          (virStoragePoolPtr pool,
                                                          const char *xmldesc,
                                                          unsigned int flags);
+virStorageVolPtr        virStorageVolClone              (virStorageVolPtr vol,
+                                                         const char *xmldesc,
+                                                         unsigned int flags);
 int                     virStorageVolDelete             (virStorageVolPtr vol,
                                                          unsigned int flags);
 int                     virStorageVolRef                (virStorageVolPtr vol);
diff --git a/qemud/remote.c b/qemud/remote.c
index e27820f..b5e27df 100644
--- a/qemud/remote.c
+++ b/qemud/remote.c
@@ -3831,6 +3831,32 @@ remoteDispatchStorageVolCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
     return 0;
 }
 
+static int
+remoteDispatchStorageVolClone (struct qemud_server *server ATTRIBUTE_UNUSED,
+                               struct qemud_client *client ATTRIBUTE_UNUSED,
+                               virConnectPtr conn,
+                               remote_error *rerr,
+                               remote_storage_vol_clone_args *args,
+                               remote_storage_vol_clone_ret *ret)
+{
+    virStorageVolPtr vol, newvol;
+
+    vol = get_nonnull_storage_vol (conn, args->vol);
+    if (vol == NULL) {
+        remoteDispatchConnError(rerr, conn);
+        return -1;
+    }
+
+    newvol = virStorageVolClone (vol, args->xml, args->flags);
+    if (newvol == NULL) {
+        remoteDispatchConnError(rerr, conn);
+        return -1;
+    }
+
+    make_nonnull_storage_vol (&ret->vol, newvol);
+    virStorageVolFree(newvol);
+    return 0;
+}
 
 static int
 remoteDispatchStorageVolDelete (struct qemud_server *server ATTRIBUTE_UNUSED,
diff --git a/qemud/remote_dispatch_args.h b/qemud/remote_dispatch_args.h
index 6573729..b115038 100644
--- a/qemud/remote_dispatch_args.h
+++ b/qemud/remote_dispatch_args.h
@@ -103,3 +103,4 @@
     remote_node_device_re_attach_args val_remote_node_device_re_attach_args;
     remote_node_device_reset_args val_remote_node_device_reset_args;
     remote_domain_get_security_label_args val_remote_domain_get_security_label_args;
+    remote_storage_vol_clone_args val_remote_storage_vol_clone_args;
diff --git a/qemud/remote_dispatch_prototypes.h b/qemud/remote_dispatch_prototypes.h
index c44e5ce..b671fbc 100644
--- a/qemud/remote_dispatch_prototypes.h
+++ b/qemud/remote_dispatch_prototypes.h
@@ -793,6 +793,13 @@ static int remoteDispatchStoragePoolUndefine(
     remote_error *err,
     remote_storage_pool_undefine_args *args,
     void *ret);
+static int remoteDispatchStorageVolClone(
+    struct qemud_server *server,
+    struct qemud_client *client,
+    virConnectPtr conn,
+    remote_error *err,
+    remote_storage_vol_clone_args *args,
+    remote_storage_vol_clone_ret *ret);
 static int remoteDispatchStorageVolCreateXml(
     struct qemud_server *server,
     struct qemud_client *client,
diff --git a/qemud/remote_dispatch_ret.h b/qemud/remote_dispatch_ret.h
index 136b1cc..e89f02f 100644
--- a/qemud/remote_dispatch_ret.h
+++ b/qemud/remote_dispatch_ret.h
@@ -88,3 +88,4 @@
     remote_node_device_list_caps_ret val_remote_node_device_list_caps_ret;
     remote_domain_get_security_label_ret val_remote_domain_get_security_label_ret;
     remote_node_get_security_model_ret val_remote_node_get_security_model_ret;
+    remote_storage_vol_clone_ret val_remote_storage_vol_clone_ret;
diff --git a/qemud/remote_dispatch_table.h b/qemud/remote_dispatch_table.h
index 75f184b..e19a299 100644
--- a/qemud/remote_dispatch_table.h
+++ b/qemud/remote_dispatch_table.h
@@ -607,13 +607,18 @@
     .args_filter = (xdrproc_t) xdr_remote_node_device_reset_args,
     .ret_filter = (xdrproc_t) xdr_void,
 },
-{   /* DomainGetSecurityLabel => 118 */
+{   /* DomainGetSecurityLabel => 121 */
     .fn = (dispatch_fn) remoteDispatchDomainGetSecurityLabel,
     .args_filter = (xdrproc_t) xdr_remote_domain_get_security_label_args,
     .ret_filter = (xdrproc_t) xdr_remote_domain_get_security_label_ret,
 },
-{   /* NodeGetSecurityModel => 119 */
+{   /* NodeGetSecurityModel => 122 */
     .fn = (dispatch_fn) remoteDispatchNodeGetSecurityModel,
     .args_filter = (xdrproc_t) xdr_void,
     .ret_filter = (xdrproc_t) xdr_remote_node_get_security_model_ret,
 },
+{   /* StorageVolClone => 123 */
+    .fn = (dispatch_fn) remoteDispatchStorageVolClone,
+    .args_filter = (xdrproc_t) xdr_remote_storage_vol_clone_args,
+    .ret_filter = (xdrproc_t) xdr_remote_storage_vol_clone_ret,
+},
diff --git a/qemud/remote_protocol.c b/qemud/remote_protocol.c
index 7f7c628..605321f 100644
--- a/qemud/remote_protocol.c
+++ b/qemud/remote_protocol.c
@@ -1992,6 +1992,28 @@ xdr_remote_storage_vol_create_xml_ret (XDR *xdrs, remote_storage_vol_create_xml_
 }
 
 bool_t
+xdr_remote_storage_vol_clone_args (XDR *xdrs, remote_storage_vol_clone_args *objp)
+{
+
+         if (!xdr_remote_nonnull_storage_vol (xdrs, &objp->vol))
+                 return FALSE;
+         if (!xdr_remote_nonnull_string (xdrs, &objp->xml))
+                 return FALSE;
+         if (!xdr_u_int (xdrs, &objp->flags))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_remote_storage_vol_clone_ret (XDR *xdrs, remote_storage_vol_clone_ret *objp)
+{
+
+         if (!xdr_remote_nonnull_storage_vol (xdrs, &objp->vol))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
 xdr_remote_storage_vol_delete_args (XDR *xdrs, remote_storage_vol_delete_args *objp)
 {
 
diff --git a/qemud/remote_protocol.h b/qemud/remote_protocol.h
index 75def5e..a22694e 100644
--- a/qemud/remote_protocol.h
+++ b/qemud/remote_protocol.h
@@ -1120,6 +1120,18 @@ struct remote_storage_vol_create_xml_ret {
 };
 typedef struct remote_storage_vol_create_xml_ret remote_storage_vol_create_xml_ret;
 
+struct remote_storage_vol_clone_args {
+        remote_nonnull_storage_vol vol;
+        remote_nonnull_string xml;
+        u_int flags;
+};
+typedef struct remote_storage_vol_clone_args remote_storage_vol_clone_args;
+
+struct remote_storage_vol_clone_ret {
+        remote_nonnull_storage_vol vol;
+};
+typedef struct remote_storage_vol_clone_ret remote_storage_vol_clone_ret;
+
 struct remote_storage_vol_delete_args {
         remote_nonnull_storage_vol vol;
         u_int flags;
@@ -1397,6 +1409,7 @@ enum remote_procedure {
         REMOTE_PROC_NODE_DEVICE_RESET = 120,
         REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL = 121,
         REMOTE_PROC_NODE_GET_SECURITY_MODEL = 122,
+        REMOTE_PROC_STORAGE_VOL_CLONE = 123,
 };
 typedef enum remote_procedure remote_procedure;
 
@@ -1605,6 +1618,8 @@ extern  bool_t xdr_remote_storage_vol_lookup_by_path_args (XDR *, remote_storage
 extern  bool_t xdr_remote_storage_vol_lookup_by_path_ret (XDR *, remote_storage_vol_lookup_by_path_ret*);
 extern  bool_t xdr_remote_storage_vol_create_xml_args (XDR *, remote_storage_vol_create_xml_args*);
 extern  bool_t xdr_remote_storage_vol_create_xml_ret (XDR *, remote_storage_vol_create_xml_ret*);
+extern  bool_t xdr_remote_storage_vol_clone_args (XDR *, remote_storage_vol_clone_args*);
+extern  bool_t xdr_remote_storage_vol_clone_ret (XDR *, remote_storage_vol_clone_ret*);
 extern  bool_t xdr_remote_storage_vol_delete_args (XDR *, remote_storage_vol_delete_args*);
 extern  bool_t xdr_remote_storage_vol_dump_xml_args (XDR *, remote_storage_vol_dump_xml_args*);
 extern  bool_t xdr_remote_storage_vol_dump_xml_ret (XDR *, remote_storage_vol_dump_xml_ret*);
@@ -1816,6 +1831,8 @@ extern bool_t xdr_remote_storage_vol_lookup_by_path_args ();
 extern bool_t xdr_remote_storage_vol_lookup_by_path_ret ();
 extern bool_t xdr_remote_storage_vol_create_xml_args ();
 extern bool_t xdr_remote_storage_vol_create_xml_ret ();
+extern bool_t xdr_remote_storage_vol_clone_args ();
+extern bool_t xdr_remote_storage_vol_clone_ret ();
 extern bool_t xdr_remote_storage_vol_delete_args ();
 extern bool_t xdr_remote_storage_vol_dump_xml_args ();
 extern bool_t xdr_remote_storage_vol_dump_xml_ret ();
diff --git a/qemud/remote_protocol.x b/qemud/remote_protocol.x
index 2d8e6a2..2b5d8c8 100644
--- a/qemud/remote_protocol.x
+++ b/qemud/remote_protocol.x
@@ -1002,6 +1002,16 @@ struct remote_storage_vol_create_xml_ret {
     remote_nonnull_storage_vol vol;
 };
 
+struct remote_storage_vol_clone_args {
+    remote_nonnull_storage_vol vol;
+    remote_nonnull_string xml;
+    unsigned flags;
+};
+
+struct remote_storage_vol_clone_ret {
+    remote_nonnull_storage_vol vol;
+};
+
 struct remote_storage_vol_delete_args {
     remote_nonnull_storage_vol vol;
     unsigned flags;
@@ -1270,7 +1280,9 @@ enum remote_procedure {
     REMOTE_PROC_NODE_DEVICE_RESET = 120,
 
     REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL = 121,
-    REMOTE_PROC_NODE_GET_SECURITY_MODEL = 122
+    REMOTE_PROC_NODE_GET_SECURITY_MODEL = 122,
+
+    REMOTE_PROC_STORAGE_VOL_CLONE = 123
 };
 
 /* Custom RPC structure. */
diff --git a/src/driver.h b/src/driver.h
index 88c2b0a..bb308ab 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -585,6 +585,10 @@ typedef char *
 typedef char *
     (*virDrvStorageVolGetPath)               (virStorageVolPtr vol);
 
+typedef virStorageVolPtr
+    (*virDrvStorageVolClone)                 (virStorageVolPtr vol,
+                                              const char *xmldesc,
+                                              unsigned int flags);
 
 
 typedef struct _virStorageDriver virStorageDriver;
@@ -636,6 +640,7 @@ struct _virStorageDriver {
     virDrvStorageVolGetInfo volGetInfo;
     virDrvStorageVolGetXMLDesc volGetXMLDesc;
     virDrvStorageVolGetPath volGetPath;
+    virDrvStorageVolClone volClone;
 };
 
 #ifdef WITH_LIBVIRTD
diff --git a/src/libvirt.c b/src/libvirt.c
index d6de773..9047d55 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -6718,7 +6718,7 @@ virStorageVolCreateXML(virStoragePoolPtr pool,
     virResetLastError();
 
     if (!VIR_IS_STORAGE_POOL(pool)) {
-        virLibConnError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
+        virLibConnError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
         return (NULL);
     }
 
@@ -6985,6 +6985,53 @@ error:
 }
 
 
+/**
+ * virStorageVolClone:
+ * @vol: pointer to storage vol to clone
+ * @xmldesc: description of volume to create
+ * @flags: flags for creation (unused, pass 0)
+ *
+ * Clone a storage volume within the parent pool.
+ * Information for the new volume (name, perms)
+ * are passed via a typical volume XML description
+ * Not all pools support cloning of volumes
+ *
+ * return the storage volume, or NULL on error
+ */
+virStorageVolPtr
+virStorageVolClone(virStorageVolPtr vol,
+                   const char *xmldesc,
+                   unsigned int flags)
+{
+    DEBUG("vol=%p, flags=%u", vol, flags);
+
+    virResetLastError();
+
+    if (!VIR_IS_STORAGE_VOL(vol)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
+        return (NULL);
+    }
+
+    if (vol->conn->flags & VIR_CONNECT_RO) {
+        virLibConnError(vol->conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+
+    if (vol->conn->storageDriver && vol->conn->storageDriver->volClone) {
+        virStorageVolPtr ret;
+        ret = vol->conn->storageDriver->volClone (vol, xmldesc, flags);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (vol->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(vol->conn);
+    return NULL;
+}
 
 
 /**
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index f7ebbc3..0f92e68 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -244,6 +244,7 @@ LIBVIRT_0.6.0 {
 	virStoragePoolRef;
 	virStorageVolRef;
 	virNodeDeviceRef;
+	virStorageVolClone;
 
 } LIBVIRT_0.5.0;
 
diff --git a/src/remote_internal.c b/src/remote_internal.c
index cc658c2..46d0628 100644
--- a/src/remote_internal.c
+++ b/src/remote_internal.c
@@ -4599,6 +4599,35 @@ done:
     return rv;
 }
 
+static virStorageVolPtr
+remoteStorageVolClone (virStorageVolPtr vol, const char *xmlDesc,
+                       unsigned int flags)
+{
+    virStorageVolPtr newvol = NULL;
+    remote_storage_vol_clone_args args;
+    remote_storage_vol_clone_ret ret;
+    struct private_data *priv = vol->conn->storagePrivateData;
+
+    remoteDriverLock(priv);
+
+    make_nonnull_storage_vol (&args.vol, vol);
+    args.xml = (char *) xmlDesc;
+    args.flags = flags;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_CLONE,
+              (xdrproc_t) xdr_remote_storage_vol_clone_args, (char *) &args,
+              (xdrproc_t) xdr_remote_storage_vol_clone_ret, (char *) &ret) == -1)
+        goto done;
+
+    newvol = get_nonnull_storage_vol (vol->conn, ret.vol);
+    xdr_free ((xdrproc_t) &xdr_remote_storage_vol_clone_ret, (char *) &ret);
+
+done:
+    remoteDriverUnlock(priv);
+    return newvol;
+}
+
 
 /*----------------------------------------------------------------------*/
 
@@ -6961,6 +6990,7 @@ static virStorageDriver storage_driver = {
     .volGetInfo = remoteStorageVolGetInfo,
     .volGetXMLDesc = remoteStorageVolDumpXML,
     .volGetPath = remoteStorageVolGetPath,
+    .volClone = remoteStorageVolClone,
 };
 
 static virDeviceMonitor dev_monitor = {
diff --git a/src/storage_backend.h b/src/storage_backend.h
index c9c1e35..af3ae59 100644
--- a/src/storage_backend.h
+++ b/src/storage_backend.h
@@ -38,6 +38,7 @@ typedef int (*virStorageBackendBuildVol)(virConnectPtr conn, virStorageVolDefPtr
 typedef int (*virStorageBackendCreateVol)(virConnectPtr conn, virStoragePoolObjPtr pool, virStorageVolDefPtr vol);
 typedef int (*virStorageBackendRefreshVol)(virConnectPtr conn, virStoragePoolObjPtr pool, virStorageVolDefPtr vol);
 typedef int (*virStorageBackendDeleteVol)(virConnectPtr conn, virStoragePoolObjPtr pool, virStorageVolDefPtr vol, unsigned int flags);
+typedef int (*virStorageBackendCloneVol)(virConnectPtr conn, virStorageVolDefPtr origvol, virStorageVolDefPtr newvol, unsigned int flags);
 
 
 typedef struct _virStorageBackend virStorageBackend;
@@ -57,6 +58,7 @@ struct _virStorageBackend {
     virStorageBackendCreateVol createVol;
     virStorageBackendRefreshVol refreshVol;
     virStorageBackendDeleteVol deleteVol;
+    virStorageBackendCloneVol cloneVol;
 };
 
 virStorageBackendPtr virStorageBackendForType(int type);
diff --git a/src/storage_backend_fs.c b/src/storage_backend_fs.c
index 7a1bba8..29a644a 100644
--- a/src/storage_backend_fs.c
+++ b/src/storage_backend_fs.c
@@ -980,7 +980,6 @@ virStorageBackendFileSystemDelete(virConnectPtr conn,
     return 0;
 }
 
-
 /**
  * Set up a volume definition to be added to a pool's volume list, but
  * don't do any file creation or allocation. By separating the two processes,
@@ -1232,6 +1231,116 @@ virStorageBackendFileSystemVolBuild(virConnectPtr conn,
     return 0;
 }
 
+/*
+ * Create a copy of a volume
+ */
+static int
+virStorageBackendFileSystemVolClone(virConnectPtr conn,
+                                    virStorageVolDefPtr origvol,
+                                    virStorageVolDefPtr newvol,
+                                    unsigned int flags ATTRIBUTE_UNUSED)
+{
+
+    int origfd = -1;
+    int newfd = -1;
+    int ret = -1;
+    size_t bytes = 1024 * 1024;
+
+    if ((origfd = open(origvol->target.path, O_RDONLY)) < 0) {
+        virReportSystemError(conn, errno,
+                             _("cannot open path '%s'"),
+                             origvol->target.path);
+        goto cleanup;
+    }
+
+    if ((newfd = open(newvol->target.path, O_RDWR | O_CREAT | O_EXCL,
+                      newvol->target.perms.mode)) < 0) {
+        virReportSystemError(conn, errno,
+                             _("cannot create path '%s'"),
+                             newvol->target.path);
+        goto cleanup;
+    }
+
+    newvol->capacity = origvol->capacity;
+
+    /* Seek to the final size, so the capacity is available upfront
+     * for progress reporting */
+    if (ftruncate(newfd, newvol->capacity) < 0) {
+        virReportSystemError(conn, errno,
+                             _("cannot extend file '%s'"),
+                             newvol->target.path);
+        goto cleanup;
+    }
+
+    int amtread = -1;
+    while (amtread != 0) {
+        char *buf[bytes];
+
+        if ((amtread = saferead(origfd, buf, bytes)) < 0) {
+            virReportSystemError(conn, errno,
+                                 _("failed reading from file '%s'"),
+                                 origvol->target.path);
+            goto cleanup;
+        }
+
+        if (safewrite(newfd, buf, amtread) < 0) {
+            virReportSystemError(conn, errno,
+                                 _("failed writing to file '%s'"),
+                                 newvol->target.path);
+            goto cleanup;
+        }
+    }
+
+    /* We can only chown/grp if root */
+    if (getuid() == 0) {
+        if (fchown(newfd, newvol->target.perms.uid,
+                   newvol->target.perms.gid) < 0) {
+            virReportSystemError(conn, errno,
+                                 _("cannot set file owner '%s'"),
+                                 newvol->target.path);
+            goto cleanup;
+        }
+    }
+    if (fchmod(newfd, newvol->target.perms.mode) < 0) {
+        virReportSystemError(conn, errno,
+                             _("cannot set file mode '%s'"),
+                             newvol->target.path);
+        goto cleanup;
+    }
+
+    /* Refresh allocation / permissions info */
+    if (virStorageBackendUpdateVolTargetInfoFD(conn, &newvol->target, newfd,
+                                               &newvol->allocation,
+                                               NULL) < 0) {
+        goto cleanup;
+    }
+
+    if (close(origfd) < 0) {
+        virReportSystemError(conn, errno,
+                             _("cannot close file '%s'"),
+                             origvol->target.path);
+        goto cleanup;
+    }
+    origfd = -1;
+
+    if (close(newfd) < 0) {
+        virReportSystemError(conn, errno,
+                             _("cannot close file '%s'"),
+                             newvol->target.path);
+        goto cleanup;
+    }
+    newfd = -1;
+
+    ret = 0;
+
+cleanup:
+    if (origfd != -1)
+        close(origfd);
+    if (newfd != -1)
+        close(newfd);
+
+    return ret;
+}
 
 /**
  * Remove a volume - just unlinks for now
@@ -1263,7 +1372,9 @@ virStorageBackendFileSystemVolRefresh(virConnectPtr conn,
                                       virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
                                       virStorageVolDefPtr vol)
 {
-    /* Refresh allocation / permissions info in case its changed */
+    /* Refresh allocation / permissions info in case its changed,
+    * but not 'capacity', since for formats like qcow2 this is only
+    * determined via the file header */
     return virStorageBackendUpdateVolInfo(conn, vol, 0);
 }
 
@@ -1277,6 +1388,7 @@ virStorageBackend virStorageBackendDirectory = {
     .createVol = virStorageBackendFileSystemVolCreate,
     .refreshVol = virStorageBackendFileSystemVolRefresh,
     .deleteVol = virStorageBackendFileSystemVolDelete,
+    .cloneVol = virStorageBackendFileSystemVolClone,
 };
 
 #if WITH_STORAGE_FS
@@ -1292,6 +1404,7 @@ virStorageBackend virStorageBackendFileSystem = {
     .createVol = virStorageBackendFileSystemVolCreate,
     .refreshVol = virStorageBackendFileSystemVolRefresh,
     .deleteVol = virStorageBackendFileSystemVolDelete,
+    .cloneVol = virStorageBackendFileSystemVolClone,
 };
 virStorageBackend virStorageBackendNetFileSystem = {
     .type = VIR_STORAGE_POOL_NETFS,
@@ -1306,5 +1419,6 @@ virStorageBackend virStorageBackendNetFileSystem = {
     .createVol = virStorageBackendFileSystemVolCreate,
     .refreshVol = virStorageBackendFileSystemVolRefresh,
     .deleteVol = virStorageBackendFileSystemVolDelete,
+    .cloneVol = virStorageBackendFileSystemVolClone,
 };
 #endif /* WITH_STORAGE_FS */
diff --git a/src/storage_driver.c b/src/storage_driver.c
index 3803474..86903bb 100644
--- a/src/storage_driver.c
+++ b/src/storage_driver.c
@@ -1350,7 +1350,6 @@ storageVolumeDelete(virStorageVolPtr obj,
         virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
                               _("volume '%s' is still being allocated."),
                               vol->name);
-
         goto cleanup;
     }
 
@@ -1532,6 +1531,118 @@ cleanup:
 
 
 
+static virStorageVolPtr
+storageVolumeClone(virStorageVolPtr obj,
+                   const char *xmldesc,
+                   unsigned int flags) {
+    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
+    virStoragePoolObjPtr pool;
+    virStorageBackendPtr backend;
+    virStorageVolDefPtr origvol = NULL, newvol = NULL;
+    virStorageVolPtr ret = NULL, volobj = NULL;
+    int buildret;
+
+    storageDriverLock(driver);
+    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
+    storageDriverUnlock(driver);
+
+    if (!pool) {
+        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
+                              "%s", _("no storage pool with matching uuid"));
+        goto cleanup;
+    }
+
+    if (!virStoragePoolObjIsActive(pool)) {
+        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
+                              "%s", _("storage pool is not active"));
+        goto cleanup;
+    }
+
+    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
+        goto cleanup;
+
+    origvol = virStorageVolDefFindByName(pool, obj->name);
+
+    if (!origvol) {
+        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
+                              "%s", _("no storage vol with matching name"));
+        goto cleanup;
+    }
+
+    newvol = virStorageVolDefParse(obj->conn, pool->def, xmldesc, NULL);
+    if (newvol == NULL)
+        goto cleanup;
+
+    if (virStorageVolDefFindByName(pool, newvol->name)) {
+        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
+                              _("storage vol '%s' already exists"),
+                              newvol->name);
+        goto cleanup;
+    }
+
+    if (!backend->cloneVol || !backend->buildVol) {
+        virStorageReportError(obj->conn, VIR_ERR_NO_SUPPORT,
+                              "%s", _("storage pool does not support volume cloning"));
+        goto cleanup;
+    }
+
+    if (origvol->building) {
+        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
+                              _("volume '%s' is still being allocated."),
+                              origvol->name);
+        goto cleanup;
+    }
+
+    if (VIR_REALLOC_N(pool->volumes.objs,
+                      pool->volumes.count+1) < 0) {
+        virReportOOMError(obj->conn);
+        goto cleanup;
+    }
+
+    if (backend->refreshVol &&
+        backend->refreshVol(obj->conn, pool, origvol) < 0)
+        goto cleanup;
+
+    /* If backend supports async volume creation, we can use it here */
+    if (backend->createVol(obj->conn, pool, newvol) < 0) {
+        goto cleanup;
+    }
+
+    pool->volumes.objs[pool->volumes.count++] = newvol;
+    volobj = virGetStorageVol(obj->conn, pool->def->name, newvol->name,
+                              newvol->key);
+
+    /* Drop the pool lock during volume allocation */
+    pool->asyncjobs++;
+    virStoragePoolObjUnlock(pool);
+
+    newvol->building = 1;
+    buildret = backend->cloneVol(obj->conn, origvol, newvol, flags);
+    newvol->building = 0;
+    newvol = NULL;
+
+    virStoragePoolObjLock(pool);
+    pool->asyncjobs--;
+
+    if (buildret < 0) {
+        virStoragePoolObjUnlock(pool);
+        storageVolumeDelete(volobj, 0);
+        pool = NULL;
+        goto cleanup;
+    }
+
+    ret = volobj;
+    volobj = NULL;
+
+cleanup:
+    if (volobj)
+        virUnrefStorageVol(volobj);
+    virStorageVolDefFree(newvol);
+    if (pool)
+        virStoragePoolObjUnlock(pool);
+    return ret;
+}
+
 
 
 static virStorageDriver storageDriver = {
@@ -1569,6 +1680,7 @@ static virStorageDriver storageDriver = {
     .volGetInfo = storageVolumeGetInfo,
     .volGetXMLDesc = storageVolumeGetXMLDesc,
     .volGetPath = storageVolumeGetPath,
+    .volClone = storageVolumeClone,
 };
 
 
diff --git a/src/virsh.c b/src/virsh.c
index 26764a7..feaef94 100644
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -4031,6 +4031,74 @@ cmdVolCreate(vshControl *ctl, const vshCmd *cmd)
 }
 
 /*
+ * "vol-clone" command
+ */
+static const vshCmdInfo info_vol_clone[] = {
+    {"help", gettext_noop("clone a volume.")},
+    {"desc", gettext_noop("Clone an existing volume.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_clone[] = {
+    {"pool", VSH_OT_STRING, 0, gettext_noop("pool name or uuid")},
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("orig vol name or key")},
+    {"newname", VSH_OT_STRING, VSH_OFLAG_REQ, gettext_noop("clone name")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdVolClone(vshControl *ctl, const vshCmd *cmd)
+{
+    virStorageVolPtr origvol = NULL, newvol = NULL;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    char *name, *xml = NULL;
+    int found;
+    int ret = FALSE;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        goto cleanup;
+
+    if (!(origvol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
+        goto cleanup;
+
+    name = vshCommandOptString(cmd, "newname", &found);
+    if (!found)
+        goto cleanup;
+
+    virBufferAddLit(&buf, "<volume>\n");
+    virBufferVSprintf(&buf, "  <name>%s</name>\n", name);
+    virBufferVSprintf(&buf, "  <capacity>1</capacity>\n");
+    virBufferAddLit(&buf, "</volume>\n");
+
+    if (virBufferError(&buf)) {
+        vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
+        goto cleanup;
+    }
+    xml = virBufferContentAndReset(&buf);
+
+    newvol = virStorageVolClone(origvol, xml, 0);
+
+    if (newvol != NULL) {
+        vshPrint(ctl, _("Vol %s cloned from %s\n"),
+                 virStorageVolGetName(newvol), virStorageVolGetName(origvol));
+        virStorageVolFree(newvol);
+    } else {
+        vshError(ctl, FALSE, _("Failed to clone vol from %s"),
+                 virStorageVolGetName(origvol));
+        goto cleanup;
+    }
+
+    ret = TRUE;
+
+cleanup:
+    if (xml)
+        free(xml);
+    if (origvol)
+        virStorageVolFree(origvol);
+    return ret;
+}
+
+/*
  * "vol-delete" command
  */
 static const vshCmdInfo info_vol_delete[] = {
@@ -5931,6 +5999,7 @@ static const vshCmdDef commands[] = {
 
     {"vol-create", cmdVolCreate, opts_vol_create, info_vol_create},
     {"vol-create-as", cmdVolCreateAs, opts_vol_create_as, info_vol_create_as},
+    {"vol-clone", cmdVolClone, opts_vol_clone, info_vol_clone},
     {"vol-delete", cmdVolDelete, opts_vol_delete, info_vol_delete},
     {"vol-dumpxml", cmdVolDumpXML, opts_vol_dumpxml, info_vol_dumpxml},
     {"vol-info", cmdVolInfo, opts_vol_info, info_vol_info},
