[libvirt] RFC: Exposing backing chains in <domain> XML

Eric Blake eblake at redhat.com
Thu Mar 13 15:26:30 UTC 2014


On 03/12/2014 05:34 PM, Eric Blake wrote:
> 
> Code-wise, I'm looking at splitting 'struct _virDomainDiskDef' into two
> parts.  The outermost part is _virDomainDiskDef, which tracks anything
> tied to the guest view, or to the device as a whole (<target>, <alias>,
> <address>); the inner part is a new _virDomainDiskSrcDef, which tracks
> anything related to a host view (node name, <source>, <driver>,
> <backingStore>), and where each backingStore is also a
> _virDomainDiskSrcDef, as a recursive structure - we just special case
> the output so that the first _virDomainDiskSrcDef feeds the XML of
> <disk> element, while all other _virDomainDiskSrcDef feed the XML of a
> <backingStore>.

This won't compile, but here's the split I'm currently envisioning.
Also, Peter reminded me on IRC that it is going to be nicer if the
host-side source resource can be reusable in the src/util/virstorage
framework, which means I need to move the inner struct out of
conf/domain_conf.h (conf/ can use util/, but util/ cannot use conf/):

diff --git i/src/conf/domain_conf.h w/src/conf/domain_conf.h
index 37191a8..5a3cd77 100644
--- i/src/conf/domain_conf.h
+++ w/src/conf/domain_conf.h
@@ -688,108 +688,119 @@ enum virDomainDiskSourcePoolMode {
...
 };
 typedef virDomainDiskSourcePoolDef *virDomainDiskSourcePoolDefPtr;

-/* Stores the virtual disk configuration */
-struct _virDomainDiskDef {
-    int type;
-    int device;
-    int bus;
+struct _virDomainDiskSourceDef {
+    int type; /* enum virDomainDiskType */
     char *src;
-    char *dst;
-    int tray_status;
-    int removable;
-    int protocol;
+    int protocol; /* enum virDomainDiskProtocol */
     size_t nhosts;
     virDomainDiskHostDefPtr hosts;
     virDomainDiskSourcePoolDefPtr srcpool;
     struct {
         char *username;
         int secretType; /* enum virDomainDiskSecretType */
         union {
             unsigned char uuid[VIR_UUID_BUFLEN];
             char *usage;
         } secret;
     } auth;
+    virStorageEncryptionPtr encryption;
     char *driverName;
     int format; /* enum virStorageFileFormat */
     virStorageFileMetadataPtr backingChain;

+    size_t nseclabels;
+    virSecurityDeviceLabelDefPtr *seclabels;
+
+    bool noBacking;
+    virDomainDiskSourceDefPtr backing;
+};
+typedef struct _virDomainDiskSourceDef virDomainDiskSourceDef;
+typedef virDomainDiskSourceDef *virDomainDiskSourceDefPtr;
+
+/* Stores the virtual disk configuration */
+struct _virDomainDiskDef {
+    virDomainDiskSourceDef src;
+
+    int device; /* enum virDomainDiskDevice */
+    int bus; /* enum virDomainDiskBus */
+    char *dst;
+    int tray_status;
+    int removable;
+    virStorageFileMetadataPtr backingChain;
+
     char *mirror;
     int mirrorFormat; /* enum virStorageFileFormat */
     bool mirroring;

     struct {
         unsigned int cylinders;
         unsigned int heads;
         unsigned int sectors;
         int trans;
     } geometry;

     struct {
         unsigned int logical_block_size;
         unsigned int physical_block_size;
     } blockio;

     virDomainBlockIoTuneInfo blkdeviotune;

     char *serial;
     char *wwn;
     char *vendor;
     char *product;
     int cachemode;
     int error_policy;  /* enum virDomainDiskErrorPolicy */
     int rerror_policy; /* enum virDomainDiskErrorPolicy */
     int iomode;
     int ioeventfd;
     int event_idx;
     int copy_on_read;
     int snapshot; /* enum virDomainSnapshotLocation, snapshot_conf.h */
     int startupPolicy; /* enum virDomainStartupPolicy */
     bool readonly;
     bool shared;
     bool transient;
     virDomainDeviceInfo info;
-    virStorageEncryptionPtr encryption;
     bool rawio_specified;
     int rawio; /* no = 0, yes = 1 */
     int sgio; /* enum virDomainDeviceSGIO */
     int discard; /* enum virDomainDiskDiscard */
-
-    size_t nseclabels;
-    virSecurityDeviceLabelDefPtr *seclabels;
 };



If I did the split right, then everything that is per-device remains in
the outer struct, and everything that is per-file is in the inner
struct.  noBacking is required to know whether 'backing==NULL' implies
<backingStore/> as an explicit end of chain, vs. omitting the subelement
from older versions or user input that is still expecting libvirt to
populate the backing chain into the xml.  Another interesting
observation - we have obviously not done much with chains of encrypted
volumes, because just a little thought makes it obvious that <auth> and
storageEncryption must be per-file attributes (it is feasible to have a
chain of two separate encrypted qcow2 images[*], where the two images
need SEPARATE passwords) while the current design of only one <auth> per
device doesn't cope.  Similarly, we can finally express the fact that
the security label on backing stores is readonly while the top-most file
is read-write; as well as designate when we have changed a backing store
to read-write in order to update metadata such as during a commit
operation (there are some FIXMEs in qemu_driver about knowing when to
revert read-write privileges of backing stores if a block commit extends
over a libvirtd restart).

[*] Of course, I must give the caveat that I'd highly recommend AGAINST
using qcow2 encryption - it is known to be a lousy implementation, when
compared to LUKS.

In making the proposed split, I noticed that we've abused the <driver>
element to contain a hodgepodge of things that are per-device (for
example, cache is a per-device setting, while format is a per-file
setting), so I'm now trying to figure out how to tweak the XML to
express the difference.  I may end up keeping <driver> only at the top
level, and adding a new <format> subelement inside <backingStore>, then
for back-compat reasons duplicate <driver format='...'/> and <format> at
the top level, or teaching the disk source formatter to merely append in
a string of device-level attributes when formatting the active disk of
the chain.

Peter, how does this split coincide with what you were looking at?

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 604 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20140313/cd0c5e66/attachment-0001.sig>


More information about the libvir-list mailing list