[PATCH 1/5] conf: store snapshot source as pointer, for easier manipulation

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

 



As part of the work on backing chains, I'm finding that it would
be easier to directly manipulate chains of pointers (adding a
snapshot merely adjusts pointers to form the correct list) rather
than copy data from one struct to another. This patch converts
snapshot source to be a pointer.

In this patch, the pointer is ALWAYS allocated (any code that
increases ndisks now also allocates a source pointer for each
new disk), and all other changes are just mechanical fallout of
the new type; there should be no functional change.  It is
possible that we may want to leave the pointer NULL for internal
snapshots in a later patch, but as that requires a closer audit
of the source to ensure we don't fault on a null dereference, I
didn't do it here.

* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Change
type of src.
* src/conf/snapshot_conf.c: Adjust all clients.
* src/qemu/qemu_conf.c: Likewise.
* src/qemu/qemu_driver.c: Likewise.

Signed-off-by: Eric Blake <eblake@xxxxxxxxxx>
---
 src/conf/snapshot_conf.c |  56 ++++++++++++++------------
 src/conf/snapshot_conf.h |   2 +-
 src/qemu/qemu_conf.c     |   2 +-
 src/qemu/qemu_driver.c   | 100 +++++++++++++++++++++++------------------------
 4 files changed, 83 insertions(+), 77 deletions(-)

diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c
index b0e4700..441162c 100644
--- a/src/conf/snapshot_conf.c
+++ b/src/conf/snapshot_conf.c
@@ -83,7 +83,8 @@ static void
 virDomainSnapshotDiskDefClear(virDomainSnapshotDiskDefPtr disk)
 {
     VIR_FREE(disk->name);
-    virStorageSourceClear(&disk->src);
+    virStorageSourceFree(disk->src);
+    disk->src = NULL;
 }

 void virDomainSnapshotDefFree(virDomainSnapshotDefPtr def)
@@ -113,6 +114,9 @@ virDomainSnapshotDiskDefParseXML(xmlNodePtr node,
     char *type = NULL;
     xmlNodePtr cur;

+    if (VIR_ALLOC(def->src) < 0)
+        goto cleanup;
+
     def->name = virXMLPropString(node, "name");
     if (!def->name) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -132,35 +136,35 @@ virDomainSnapshotDiskDefParseXML(xmlNodePtr node,
     }

     if ((type = virXMLPropString(node, "type"))) {
-        if ((def->src.type = virStorageTypeFromString(type)) <= 0 ||
-            def->src.type == VIR_STORAGE_TYPE_VOLUME ||
-            def->src.type == VIR_STORAGE_TYPE_DIR) {
+        if ((def->src->type = virStorageTypeFromString(type)) <= 0 ||
+            def->src->type == VIR_STORAGE_TYPE_VOLUME ||
+            def->src->type == VIR_STORAGE_TYPE_DIR) {
             virReportError(VIR_ERR_XML_ERROR,
                            _("unknown disk snapshot type '%s'"), type);
             goto cleanup;
         }
     } else {
-        def->src.type = VIR_STORAGE_TYPE_FILE;
+        def->src->type = VIR_STORAGE_TYPE_FILE;
     }

     for (cur = node->children; cur; cur = cur->next) {
         if (cur->type != XML_ELEMENT_NODE)
             continue;

-        if (!def->src.path &&
+        if (!def->src->path &&
             xmlStrEqual(cur->name, BAD_CAST "source")) {

-            if (virDomainDiskSourceParse(cur, &def->src) < 0)
+            if (virDomainDiskSourceParse(cur, def->src) < 0)
                 goto cleanup;

-        } else if (!def->src.format &&
+        } else if (!def->src->format &&
                    xmlStrEqual(cur->name, BAD_CAST "driver")) {
             char *driver = virXMLPropString(cur, "type");
             if (driver) {
-                def->src.format = virStorageFileFormatTypeFromString(driver);
-                if (def->src.format < VIR_STORAGE_FILE_BACKING) {
+                def->src->format = virStorageFileFormatTypeFromString(driver);
+                if (def->src->format < VIR_STORAGE_FILE_BACKING) {
                     virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                                   def->src.format <= 0
+                                   def->src->format <= 0
                                    ? _("unknown disk snapshot driver '%s'")
                                    : _("disk format '%s' lacks backing file "
                                        "support"),
@@ -173,7 +177,7 @@ virDomainSnapshotDiskDefParseXML(xmlNodePtr node,
         }
     }

-    if (!def->snapshot && (def->src.path || def->src.format))
+    if (!def->snapshot && (def->src->path || def->src->format))
         def->snapshot = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;

     ret = 0;
@@ -506,12 +510,12 @@ virDomainSnapshotAlignDisks(virDomainSnapshotDefPtr def,
                            disk->name, tmp);
             goto cleanup;
         }
-        if (disk->src.path &&
+        if (disk->src->path &&
             disk->snapshot != VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                            _("file '%s' for disk '%s' requires "
                              "use of external snapshot mode"),
-                           disk->src.path, disk->name);
+                           disk->src->path, disk->name);
             goto cleanup;
         }
         if (STRNEQ(disk->name, def->dom->disks[idx]->dst)) {
@@ -534,11 +538,13 @@ virDomainSnapshotAlignDisks(virDomainSnapshotDefPtr def,
         if (inuse)
             continue;
         disk = &def->disks[ndisks++];
+        if (VIR_ALLOC(disk->src) < 0)
+            goto cleanup;
         if (VIR_STRDUP(disk->name, def->dom->disks[i]->dst) < 0)
             goto cleanup;
         disk->index = i;
         disk->snapshot = def->dom->disks[i]->snapshot;
-        disk->src.type = VIR_STORAGE_TYPE_FILE;
+        disk->src->type = VIR_STORAGE_TYPE_FILE;
         if (!disk->snapshot)
             disk->snapshot = default_snapshot;
     }
@@ -551,17 +557,17 @@ virDomainSnapshotAlignDisks(virDomainSnapshotDefPtr def,
         virDomainSnapshotDiskDefPtr disk = &def->disks[i];

         if (disk->snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL &&
-            !disk->src.path) {
+            !disk->src->path) {
             const char *original = virDomainDiskGetSource(def->dom->disks[i]);
             const char *tmp;
             struct stat sb;

-            if (disk->src.type != VIR_STORAGE_TYPE_FILE) {
+            if (disk->src->type != VIR_STORAGE_TYPE_FILE) {
                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                _("cannot generate external snapshot name "
                                  "for disk '%s' on a '%s' device"),
                                disk->name,
-                               virStorageTypeToString(disk->src.type));
+                               virStorageTypeToString(disk->src->type));
                 goto cleanup;
             }

@@ -583,7 +589,7 @@ virDomainSnapshotAlignDisks(virDomainSnapshotDefPtr def,

             tmp = strrchr(original, '.');
             if (!tmp || strchr(tmp, '/')) {
-                if (virAsprintf(&disk->src.path, "%s.%s", original,
+                if (virAsprintf(&disk->src->path, "%s.%s", original,
                                 def->name) < 0)
                     goto cleanup;
             } else {
@@ -592,7 +598,7 @@ virDomainSnapshotAlignDisks(virDomainSnapshotDefPtr def,
                                    _("integer overflow"));
                     goto cleanup;
                 }
-                if (virAsprintf(&disk->src.path, "%.*s.%s",
+                if (virAsprintf(&disk->src->path, "%.*s.%s",
                                 (int) (tmp - original), original,
                                 def->name) < 0)
                     goto cleanup;
@@ -611,7 +617,7 @@ static void
 virDomainSnapshotDiskDefFormat(virBufferPtr buf,
                                virDomainSnapshotDiskDefPtr disk)
 {
-    int type = disk->src.type;
+    int type = disk->src->type;

     if (!disk->name)
         return;
@@ -621,7 +627,7 @@ virDomainSnapshotDiskDefFormat(virBufferPtr buf,
         virBufferAsprintf(buf, " snapshot='%s'",
                           virDomainSnapshotLocationTypeToString(disk->snapshot));

-    if (!disk->src.path && disk->src.format == 0) {
+    if (!disk->src->path && disk->src->format == 0) {
         virBufferAddLit(buf, "/>\n");
         return;
     }
@@ -629,10 +635,10 @@ virDomainSnapshotDiskDefFormat(virBufferPtr buf,
     virBufferAsprintf(buf, " type='%s'>\n", virStorageTypeToString(type));
     virBufferAdjustIndent(buf, 2);

-    if (disk->src.format > 0)
+    if (disk->src->format > 0)
         virBufferEscapeString(buf, "<driver type='%s'/>\n",
-                              virStorageFileFormatTypeToString(disk->src.format));
-    virDomainDiskSourceFormat(buf, &disk->src, 0, 0);
+                              virStorageFileFormatTypeToString(disk->src->format));
+    virDomainDiskSourceFormat(buf, disk->src, 0, 0);

     virBufferAdjustIndent(buf, -2);
     virBufferAddLit(buf, "</disk>\n");
diff --git a/src/conf/snapshot_conf.h b/src/conf/snapshot_conf.h
index 1eb697f..21b5b62 100644
--- a/src/conf/snapshot_conf.h
+++ b/src/conf/snapshot_conf.h
@@ -52,7 +52,7 @@ struct _virDomainSnapshotDiskDef {
     int index;      /* index within snapshot->dom->disks that matches name */
     int snapshot;   /* virDomainSnapshotLocation */

-    virStorageSource src; /* new wrapper file when snapshot is external */
+    virStorageSourcePtr src; /* new wrapper file when snapshot is external */
 };

 /* Stores the complete snapshot metadata */
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index f273056..c14d700 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1427,7 +1427,7 @@ int
 qemuTranslateSnapshotDiskSourcePool(virConnectPtr conn ATTRIBUTE_UNUSED,
                                     virDomainSnapshotDiskDefPtr def)
 {
-    if (def->src.type != VIR_STORAGE_TYPE_VOLUME)
+    if (def->src->type != VIR_STORAGE_TYPE_VOLUME)
         return 0;

     virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 6fda50d..bf46d5d 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -12190,14 +12190,14 @@ qemuDomainSnapshotCreateInactiveExternal(virQEMUDriverPtr driver,
         if (snapdisk->snapshot != VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL)
             continue;

-        if (!snapdisk->src.format)
-            snapdisk->src.format = VIR_STORAGE_FILE_QCOW2;
+        if (!snapdisk->src->format)
+            snapdisk->src->format = VIR_STORAGE_FILE_QCOW2;

         /* creates cmd line args: qemu-img create -f qcow2 -o */
         if (!(cmd = virCommandNewArgList(qemuImgPath,
                                          "create",
                                          "-f",
-                                         virStorageFileFormatTypeToString(snapdisk->src.format),
+                                         virStorageFileFormatTypeToString(snapdisk->src->format),
                                          "-o",
                                          NULL)))
             goto cleanup;
@@ -12221,10 +12221,10 @@ qemuDomainSnapshotCreateInactiveExternal(virQEMUDriverPtr driver,
         }

         /* adds cmd line args: /path/to/target/file */
-        virCommandAddArg(cmd, snapdisk->src.path);
+        virCommandAddArg(cmd, snapdisk->src->path);

         /* If the target does not exist, we're going to create it possibly */
-        if (!virFileExists(snapdisk->src.path))
+        if (!virFileExists(snapdisk->src->path))
             ignore_value(virBitmapSetBit(created, i));

         if (virCommandRun(cmd, NULL) < 0)
@@ -12241,11 +12241,11 @@ qemuDomainSnapshotCreateInactiveExternal(virQEMUDriverPtr driver,

         if (snapdisk->snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
             VIR_FREE(defdisk->src.path);
-            if (VIR_STRDUP(defdisk->src.path, snapdisk->src.path) < 0) {
+            if (VIR_STRDUP(defdisk->src.path, snapdisk->src->path) < 0) {
                 /* we cannot rollback here in a sane way */
                 goto cleanup;
             }
-            defdisk->src.format = snapdisk->src.format;
+            defdisk->src.format = snapdisk->src->format;
         }
     }

@@ -12259,9 +12259,9 @@ qemuDomainSnapshotCreateInactiveExternal(virQEMUDriverPtr driver,
         ssize_t bit = -1;
         while ((bit = virBitmapNextSetBit(created, bit)) >= 0) {
             snapdisk = &(snap->def->disks[bit]);
-            if (unlink(snapdisk->src.path) < 0)
+            if (unlink(snapdisk->src->path) < 0)
                 VIR_WARN("Failed to remove snapshot image '%s'",
-                         snapdisk->src.path);
+                         snapdisk->src->path);
         }
     }
     virBitmapFree(created);
@@ -12422,7 +12422,7 @@ qemuDomainSnapshotPrepareDiskExternalBackingActive(virDomainDiskDefPtr disk)
 static int
 qemuDomainSnapshotPrepareDiskExternalOverlayActive(virDomainSnapshotDiskDefPtr disk)
 {
-    int actualType = virStorageSourceGetActualType(&disk->src);
+    int actualType = virStorageSourceGetActualType(disk->src);

     switch ((virStorageType) actualType) {
     case VIR_STORAGE_TYPE_BLOCK:
@@ -12430,7 +12430,7 @@ qemuDomainSnapshotPrepareDiskExternalOverlayActive(virDomainSnapshotDiskDefPtr d
         return 0;

     case VIR_STORAGE_TYPE_NETWORK:
-        switch ((virStorageNetProtocol) disk->src.protocol) {
+        switch ((virStorageNetProtocol) disk->src->protocol) {
         case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
             return 0;

@@ -12447,7 +12447,7 @@ qemuDomainSnapshotPrepareDiskExternalOverlayActive(virDomainSnapshotDiskDefPtr d
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("external active snapshots are not supported on "
                              "'network' disks using '%s' protocol"),
-                           virStorageNetProtocolTypeToString(disk->src.protocol));
+                           virStorageNetProtocolTypeToString(disk->src->protocol));
             return -1;

         }
@@ -12470,7 +12470,7 @@ qemuDomainSnapshotPrepareDiskExternalOverlayActive(virDomainSnapshotDiskDefPtr d
 static int
 qemuDomainSnapshotPrepareDiskExternalOverlayInactive(virDomainSnapshotDiskDefPtr disk)
 {
-    int actualType = virStorageSourceGetActualType(&disk->src);
+    int actualType = virStorageSourceGetActualType(disk->src);

     switch ((virStorageType) actualType) {
     case VIR_STORAGE_TYPE_BLOCK:
@@ -12522,33 +12522,33 @@ qemuDomainSnapshotPrepareDiskExternal(virConnectPtr conn,
             return -1;
     }

-    if (virStorageFileInit(&snapdisk->src) < 0)
+    if (virStorageFileInit(snapdisk->src) < 0)
         return -1;

-    if (virStorageFileStat(&snapdisk->src, &st) < 0) {
+    if (virStorageFileStat(snapdisk->src, &st) < 0) {
         if (errno != ENOENT) {
             virReportSystemError(errno,
                                  _("unable to stat for disk %s: %s"),
-                                 snapdisk->name, snapdisk->src.path);
+                                 snapdisk->name, snapdisk->src->path);
             goto cleanup;
         } else if (reuse) {
             virReportSystemError(errno,
                                  _("missing existing file for disk %s: %s"),
-                                 snapdisk->name, snapdisk->src.path);
+                                 snapdisk->name, snapdisk->src->path);
             goto cleanup;
         }
     } else if (!S_ISBLK(st.st_mode) && st.st_size && !reuse) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("external snapshot file for disk %s already "
                          "exists and is not a block device: %s"),
-                       snapdisk->name, snapdisk->src.path);
+                       snapdisk->name, snapdisk->src->path);
         goto cleanup;
     }

     ret = 0;

  cleanup:
-    virStorageFileDeinit(&snapdisk->src);
+    virStorageFileDeinit(snapdisk->src);
     return ret;
 }

@@ -12670,15 +12670,15 @@ qemuDomainSnapshotPrepare(virConnectPtr conn,
             break;

         case VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL:
-            if (!disk->src.format) {
-                disk->src.format = VIR_STORAGE_FILE_QCOW2;
-            } else if (disk->src.format != VIR_STORAGE_FILE_QCOW2 &&
-                       disk->src.format != VIR_STORAGE_FILE_QED) {
+            if (!disk->src->format) {
+                disk->src->format = VIR_STORAGE_FILE_QCOW2;
+            } else if (disk->src->format != VIR_STORAGE_FILE_QCOW2 &&
+                       disk->src->format != VIR_STORAGE_FILE_QED) {
                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                _("external snapshot format for disk %s "
                                  "is unsupported: %s"),
                                disk->name,
-                               virStorageFileFormatTypeToString(disk->src.format));
+                               virStorageFileFormatTypeToString(disk->src->format));
                 goto cleanup;
             }

@@ -12777,7 +12777,7 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
     char *newsource = NULL;
     virStorageNetHostDefPtr newhosts = NULL;
     virStorageNetHostDefPtr persistHosts = NULL;
-    int format = snap->src.format;
+    int format = snap->src->format;
     const char *formatStr = NULL;
     char *persistSource = NULL;
     int ret = -1;
@@ -12793,27 +12793,27 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
     if (virAsprintf(&device, "drive-%s", disk->info.alias) < 0)
         goto cleanup;

-    /* XXX Here, we know we are about to alter disk->src.backingStore if
+    /* XXX Here, we know we are about to alter disk->src->backingStore if
      * successful, so we nuke the existing chain so that future commands will
      * recompute it.  Better would be storing the chain ourselves rather than
      * reprobing, but this requires modifying domain_conf and our XML to fully
      * track the chain across libvirtd restarts.  */
     virStorageSourceClearBackingStore(&disk->src);

-    if (virStorageFileInit(&snap->src) < 0)
+    if (virStorageFileInit(snap->src) < 0)
         goto cleanup;

-    if (qemuGetDriveSourceString(&snap->src, NULL, &source) < 0)
+    if (qemuGetDriveSourceString(snap->src, NULL, &source) < 0)
         goto cleanup;

-    if (VIR_STRDUP(newsource, snap->src.path) < 0)
+    if (VIR_STRDUP(newsource, snap->src->path) < 0)
         goto cleanup;

     if (persistDisk &&
-        VIR_STRDUP(persistSource, snap->src.path) < 0)
+        VIR_STRDUP(persistSource, snap->src->path) < 0)
         goto cleanup;

-    switch ((virStorageType)snap->src.type) {
+    switch ((virStorageType)snap->src->type) {
     case VIR_STORAGE_TYPE_BLOCK:
         reuse = true;
         /* fallthrough */
@@ -12838,15 +12838,15 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
         break;

     case VIR_STORAGE_TYPE_NETWORK:
-        switch (snap->src.protocol) {
+        switch (snap->src->protocol) {
         case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
-            if (!(newhosts = virStorageNetHostDefCopy(snap->src.nhosts,
-                                                      snap->src.hosts)))
+            if (!(newhosts = virStorageNetHostDefCopy(snap->src->nhosts,
+                                                      snap->src->hosts)))
                 goto cleanup;

             if (persistDisk &&
-                !(persistHosts = virStorageNetHostDefCopy(snap->src.nhosts,
-                                                          snap->src.hosts)))
+                !(persistHosts = virStorageNetHostDefCopy(snap->src->nhosts,
+                                                          snap->src->hosts)))
                 goto cleanup;

             break;
@@ -12855,7 +12855,7 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
             virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                            _("snapshots on volumes using '%s' protocol "
                              "are not supported"),
-                           virStorageNetProtocolTypeToString(snap->src.protocol));
+                           virStorageNetProtocolTypeToString(snap->src->protocol));
             goto cleanup;
         }
         break;
@@ -12866,13 +12866,13 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
     case VIR_STORAGE_TYPE_LAST:
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                        _("snapshots are not supported on '%s' volumes"),
-                       virStorageTypeToString(snap->src.type));
+                       virStorageTypeToString(snap->src->type));
         goto cleanup;
     }

     /* create the actual snapshot */
-    if (snap->src.format)
-        formatStr = virStorageFileFormatTypeToString(snap->src.format);
+    if (snap->src->format)
+        formatStr = virStorageFileFormatTypeToString(snap->src->format);

     /* The monitor is only accessed if qemu doesn't support transactions.
      * Otherwise the following monitor command only constructs the command.
@@ -12904,9 +12904,9 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,

     disk->src.path = newsource;
     disk->src.format = format;
-    disk->src.type = snap->src.type;
-    disk->src.protocol = snap->src.protocol;
-    disk->src.nhosts = snap->src.nhosts;
+    disk->src.type = snap->src->type;
+    disk->src.protocol = snap->src->protocol;
+    disk->src.nhosts = snap->src->nhosts;
     disk->src.hosts = newhosts;

     newsource = NULL;
@@ -12919,9 +12919,9 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,

         persistDisk->src.path = persistSource;
         persistDisk->src.format = format;
-        persistDisk->src.type = snap->src.type;
-        persistDisk->src.protocol = snap->src.protocol;
-        persistDisk->src.nhosts = snap->src.nhosts;
+        persistDisk->src.type = snap->src->type;
+        persistDisk->src.protocol = snap->src->protocol;
+        persistDisk->src.nhosts = snap->src->nhosts;
         persistDisk->src.hosts = persistHosts;

         persistSource = NULL;
@@ -12929,15 +12929,15 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
     }

  cleanup:
-    if (need_unlink && virStorageFileUnlink(&snap->src))
+    if (need_unlink && virStorageFileUnlink(snap->src))
         VIR_WARN("unable to unlink just-created %s", source);
-    virStorageFileDeinit(&snap->src);
+    virStorageFileDeinit(snap->src);
     VIR_FREE(device);
     VIR_FREE(source);
     VIR_FREE(newsource);
     VIR_FREE(persistSource);
-    virStorageNetHostDefFree(snap->src.nhosts, newhosts);
-    virStorageNetHostDefFree(snap->src.nhosts, persistHosts);
+    virStorageNetHostDefFree(snap->src->nhosts, newhosts);
+    virStorageNetHostDefFree(snap->src->nhosts, persistHosts);
     return ret;
 }

-- 
1.9.0

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]