[libvirt] The quest for virStorageVolResize()
by Zeeshan Ali (Khattak)
Hi everyone,
In Boxes we'll need to change the size of the storage volumes (we
use qcow2 files) but turns out that there is no virStorageVolResize()
yet[1]. In my chat with Daniel on IRC, he mentioned that this would be
a trivial task so I thought I should try to do it myself. I've been
looking into this for several hours now and haven't gotten very far. I
guess Daniel overestimated my skills of deciphering complicated code.
:) Attached is my very much WIP patch that at least builds but doesn't
exactly work yet:
virsh # vol-resize 'Microsoft Windows XP.qcow2' '4G' gnome-boxes
error: Failed to change size of volume 'Microsoft Windows XP.qcow2' to 4G
error: this function is not supported by the connection driver:
virStorageVolResize
---------------------
If anyone can have a look and tell me if I'm going anywhere towards
the right direction and what level of indirection I'm missing here,
that would be awesome!
--
Regards,
Zeeshan Ali (Khattak)
FSF member#5124
[1] Yes, I know there is a virDomainBlockResize but thats limited to
running domains and I haven't yet figured if it can be nicely binded
in libvirt-glib. Probably we'll want one function in libvirt-glib that
will abstract both virDomainBlockResize() and virStorageVolResize().
12 years, 9 months
[libvirt] [libvirt-glib] Prefer 'for' over 'while'
by Zeeshan Ali (Khattak)
From: "Zeeshan Ali (Khattak)" <zeeshanak(a)gnome.org>
In this particular case 'for' seems like a more natural choice as then
we don't need to update the iterator (which we were forgetting to do and
causing a hang in Boxes).
---
libvirt-gconfig/libvirt-gconfig-helpers.c | 5 +----
1 files changed, 1 insertions(+), 4 deletions(-)
diff --git a/libvirt-gconfig/libvirt-gconfig-helpers.c b/libvirt-gconfig/libvirt-gconfig-helpers.c
index c406a49..cc2e5cc 100644
--- a/libvirt-gconfig/libvirt-gconfig-helpers.c
+++ b/libvirt-gconfig/libvirt-gconfig-helpers.c
@@ -169,17 +169,14 @@ void gvir_config_xml_foreach_child(xmlNodePtr node,
g_return_if_fail(iter_func != NULL);
- it = node->children;
- while (it != NULL) {
+ for (it = node->children; it != NULL; it = it->next) {
gboolean cont;
- xmlNodePtr next = it->next;
if (xmlIsBlankNode(it))
continue;
cont = iter_func(it, opaque);
if (!cont)
break;
- it = next;
}
}
--
1.7.7.5
12 years, 9 months
[libvirt] [PATCH] Remove tabs from libvirt_public.syms & enforce it
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
* src/libvirt_public.syms: Death to tabs
* cfg.mk: Check .syms files for tabs
---
cfg.mk | 4 +-
src/libvirt_public.syms | 456 +++++++++++++++++++++++-----------------------
2 files changed, 230 insertions(+), 230 deletions(-)
diff --git a/cfg.mk b/cfg.mk
index d853caf..c13db18 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -413,11 +413,11 @@ sc_prohibit_ctype_h:
# Ensure that no C source file, docs, or rng schema uses TABs for
# indentation. Also match *.h.in files, to get libvirt.h.in. Exclude
# files in gnulib, since they're imported.
-space_indent_files=(\.(rng|s?[ch](\.in)?|html.in|py)|(daemon|tools)/.*\.in)
+space_indent_files=(\.(rng|s?[ch](\.in)?|html.in|py|syms)|(daemon|tools)/.*\.in)
sc_TAB_in_indentation:
@prohibit='^ * ' \
in_vc_files='$(space_indent_files)$$' \
- halt='indent with space, not TAB, in C, sh, html, py, and RNG schemas' \
+ halt='indent with space, not TAB, in C, sh, html, py, syms and RNG schemas' \
$(_sc_search_regexp)
ctype_re = isalnum|isalpha|isascii|isblank|iscntrl|isdigit|isgraph|islower\
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index ff018c6..141a571 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -12,283 +12,283 @@
#
LIBVIRT_0.0.3 {
global:
- virConnectClose;
- virConnectGetType;
- virConnectGetVersion;
- virConnectListDomains;
- virConnectNumOfDomains;
- virConnectOpen;
- virConnectOpenReadOnly;
-
- virDomainCreateLinux;
- virDomainDestroy;
- virDomainFree;
- virDomainGetID;
- virDomainGetInfo;
- virDomainGetMaxMemory;
- virDomainGetName;
- virDomainGetOSType;
- virDomainGetXMLDesc;
- virDomainLookupByID;
- virDomainLookupByName;
- virDomainRestore;
- virDomainResume;
- virDomainSave;
- virDomainSetMaxMemory;
- virDomainShutdown;
- virDomainSuspend;
-
- virGetVersion;
+ virConnectClose;
+ virConnectGetType;
+ virConnectGetVersion;
+ virConnectListDomains;
+ virConnectNumOfDomains;
+ virConnectOpen;
+ virConnectOpenReadOnly;
+
+ virDomainCreateLinux;
+ virDomainDestroy;
+ virDomainFree;
+ virDomainGetID;
+ virDomainGetInfo;
+ virDomainGetMaxMemory;
+ virDomainGetName;
+ virDomainGetOSType;
+ virDomainGetXMLDesc;
+ virDomainLookupByID;
+ virDomainLookupByName;
+ virDomainRestore;
+ virDomainResume;
+ virDomainSave;
+ virDomainSetMaxMemory;
+ virDomainShutdown;
+ virDomainSuspend;
+
+ virGetVersion;
};
LIBVIRT_0.0.5 {
global:
- virDomainLookupByUUID;
- virDomainGetUUID;
+ virDomainLookupByUUID;
+ virDomainGetUUID;
} LIBVIRT_0.0.3;
LIBVIRT_0.1.0 {
global:
- virInitialize;
- virNodeGetInfo;
- virDomainReboot;
-
- virCopyLastError;
- virConnSetErrorFunc;
- virResetLastError;
- virResetError;
- virConnGetLastError;
- virGetLastError;
- virSetErrorFunc;
- virConnCopyLastError;
- virConnResetLastError;
- virDefaultErrorFunc;
+ virInitialize;
+ virNodeGetInfo;
+ virDomainReboot;
+
+ virCopyLastError;
+ virConnSetErrorFunc;
+ virResetLastError;
+ virResetError;
+ virConnGetLastError;
+ virGetLastError;
+ virSetErrorFunc;
+ virConnCopyLastError;
+ virConnResetLastError;
+ virDefaultErrorFunc;
} LIBVIRT_0.0.5;
LIBVIRT_0.1.1 {
global:
- virDomainLookupByUUIDString;
- virDomainGetUUIDString;
- virDomainSetMemory;
- virDomainDefineXML;
- virDomainCreate;
- virDomainUndefine;
- virConnectListDefinedDomains;
+ virDomainLookupByUUIDString;
+ virDomainGetUUIDString;
+ virDomainSetMemory;
+ virDomainDefineXML;
+ virDomainCreate;
+ virDomainUndefine;
+ virConnectListDefinedDomains;
} LIBVIRT_0.1.0;
LIBVIRT_0.1.4 {
global:
- virDomainSetVcpus;
- virDomainPinVcpu;
- virDomainGetVcpus;
+ virDomainSetVcpus;
+ virDomainPinVcpu;
+ virDomainGetVcpus;
} LIBVIRT_0.1.1;
LIBVIRT_0.1.5 {
global:
- virConnectNumOfDefinedDomains;
+ virConnectNumOfDefinedDomains;
} LIBVIRT_0.1.4;
LIBVIRT_0.1.9 {
global:
- virDomainCoreDump;
- virDomainAttachDevice;
- virDomainDetachDevice;
+ virDomainCoreDump;
+ virDomainAttachDevice;
+ virDomainDetachDevice;
} LIBVIRT_0.1.5;
LIBVIRT_0.2.0 {
global:
- virConnectNumOfNetworks;
- virConnectListNetworks;
- virConnectNumOfDefinedNetworks;
- virConnectListDefinedNetworks;
- virNetworkLookupByName;
- virNetworkLookupByUUID;
- virNetworkLookupByUUIDString;
- virNetworkCreateXML;
- virNetworkDefineXML;
- virNetworkUndefine;
- virNetworkCreate;
- virNetworkDestroy;
- virNetworkFree;
- virNetworkGetName;
- virNetworkGetUUID;
- virNetworkGetUUIDString;
- virNetworkGetXMLDesc;
- virNetworkGetBridgeName;
+ virConnectNumOfNetworks;
+ virConnectListNetworks;
+ virConnectNumOfDefinedNetworks;
+ virConnectListDefinedNetworks;
+ virNetworkLookupByName;
+ virNetworkLookupByUUID;
+ virNetworkLookupByUUIDString;
+ virNetworkCreateXML;
+ virNetworkDefineXML;
+ virNetworkUndefine;
+ virNetworkCreate;
+ virNetworkDestroy;
+ virNetworkFree;
+ virNetworkGetName;
+ virNetworkGetUUID;
+ virNetworkGetUUIDString;
+ virNetworkGetXMLDesc;
+ virNetworkGetBridgeName;
} LIBVIRT_0.1.9;
LIBVIRT_0.2.1 {
global:
- virConnectGetCapabilities;
- virConnectGetMaxVcpus;
- virDomainGetMaxVcpus;
- virDomainGetAutostart;
- virDomainSetAutostart;
- virNetworkGetAutostart;
- virNetworkSetAutostart;
+ virConnectGetCapabilities;
+ virConnectGetMaxVcpus;
+ virDomainGetMaxVcpus;
+ virDomainGetAutostart;
+ virDomainSetAutostart;
+ virNetworkGetAutostart;
+ virNetworkSetAutostart;
} LIBVIRT_0.2.0;
LIBVIRT_0.2.3 {
global:
- virDomainGetSchedulerType;
- virDomainGetSchedulerParameters;
- virDomainSetSchedulerParameters;
+ virDomainGetSchedulerType;
+ virDomainGetSchedulerParameters;
+ virDomainSetSchedulerParameters;
} LIBVIRT_0.2.1;
LIBVIRT_0.3.0 {
global:
- virConnectGetHostname;
- virConnectGetURI;
- virDomainGetConnect;
- virNetworkGetConnect;
+ virConnectGetHostname;
+ virConnectGetURI;
+ virDomainGetConnect;
+ virNetworkGetConnect;
} LIBVIRT_0.2.3;
LIBVIRT_0.3.2 {
global:
- virDomainMigrate;
- virDomainBlockStats;
- virDomainInterfaceStats;
+ virDomainMigrate;
+ virDomainBlockStats;
+ virDomainInterfaceStats;
} LIBVIRT_0.3.0;
LIBVIRT_0.3.3 {
global:
- virNodeGetCellsFreeMemory;
- virNodeGetFreeMemory;
+ virNodeGetCellsFreeMemory;
+ virNodeGetFreeMemory;
} LIBVIRT_0.3.2;
LIBVIRT_0.4.0 {
global:
- virConnectOpenAuth;
- virConnectAuthPtrDefault;
+ virConnectOpenAuth;
+ virConnectAuthPtrDefault;
} LIBVIRT_0.3.3;
LIBVIRT_0.4.1 {
global:
- virStoragePoolGetConnect;
- virConnectNumOfStoragePools;
- virConnectNumOfDefinedStoragePools;
- virConnectListStoragePools;
- virConnectListDefinedStoragePools;
- virStoragePoolLookupByName;
- virStoragePoolLookupByUUID;
- virStoragePoolLookupByUUIDString;
- virStoragePoolLookupByVolume;
- virStoragePoolCreateXML;
- virStoragePoolDefineXML;
- virStoragePoolUndefine;
- virStoragePoolCreate;
- virStoragePoolBuild;
- virStoragePoolDestroy;
- virStoragePoolDelete;
- virStoragePoolRefresh;
- virStoragePoolFree;
- virStoragePoolGetName;
- virStoragePoolGetUUID;
- virStoragePoolGetUUIDString;
- virStoragePoolGetInfo;
- virStoragePoolGetXMLDesc;
- virStoragePoolSetAutostart;
- virStoragePoolGetAutostart;
- virStoragePoolNumOfVolumes;
- virStoragePoolListVolumes;
-
- virStorageVolGetConnect;
- virStorageVolLookupByName;
- virStorageVolLookupByKey;
- virStorageVolLookupByPath;
- virStorageVolCreateXML;
- virStorageVolDelete;
- virStorageVolFree;
- virStorageVolGetName;
- virStorageVolGetKey;
- virStorageVolGetInfo;
- virStorageVolGetXMLDesc;
- virStorageVolGetPath;
+ virStoragePoolGetConnect;
+ virConnectNumOfStoragePools;
+ virConnectNumOfDefinedStoragePools;
+ virConnectListStoragePools;
+ virConnectListDefinedStoragePools;
+ virStoragePoolLookupByName;
+ virStoragePoolLookupByUUID;
+ virStoragePoolLookupByUUIDString;
+ virStoragePoolLookupByVolume;
+ virStoragePoolCreateXML;
+ virStoragePoolDefineXML;
+ virStoragePoolUndefine;
+ virStoragePoolCreate;
+ virStoragePoolBuild;
+ virStoragePoolDestroy;
+ virStoragePoolDelete;
+ virStoragePoolRefresh;
+ virStoragePoolFree;
+ virStoragePoolGetName;
+ virStoragePoolGetUUID;
+ virStoragePoolGetUUIDString;
+ virStoragePoolGetInfo;
+ virStoragePoolGetXMLDesc;
+ virStoragePoolSetAutostart;
+ virStoragePoolGetAutostart;
+ virStoragePoolNumOfVolumes;
+ virStoragePoolListVolumes;
+
+ virStorageVolGetConnect;
+ virStorageVolLookupByName;
+ virStorageVolLookupByKey;
+ virStorageVolLookupByPath;
+ virStorageVolCreateXML;
+ virStorageVolDelete;
+ virStorageVolFree;
+ virStorageVolGetName;
+ virStorageVolGetKey;
+ virStorageVolGetInfo;
+ virStorageVolGetXMLDesc;
+ virStorageVolGetPath;
} LIBVIRT_0.4.0;
LIBVIRT_0.4.2 {
global:
- virDomainBlockPeek;
- virDomainMemoryPeek;
+ virDomainBlockPeek;
+ virDomainMemoryPeek;
} LIBVIRT_0.4.1;
LIBVIRT_0.4.5 {
global:
- virConnectFindStoragePoolSources;
+ virConnectFindStoragePoolSources;
} LIBVIRT_0.4.2;
LIBVIRT_0.5.0 {
global:
- virDomainCreateXML;
- virEventRegisterImpl;
- virConnectDomainEventRegister;
- virConnectDomainEventDeregister;
-
- virNodeNumOfDevices;
- virNodeListDevices;
- virNodeDeviceLookupByName;
- virNodeDeviceFree;
- virNodeDeviceGetXMLDesc;
- virNodeDeviceGetName;
- virNodeDeviceGetParent;
- virNodeDeviceNumOfCaps;
- virNodeDeviceListCaps;
+ virDomainCreateXML;
+ virEventRegisterImpl;
+ virConnectDomainEventRegister;
+ virConnectDomainEventDeregister;
+
+ virNodeNumOfDevices;
+ virNodeListDevices;
+ virNodeDeviceLookupByName;
+ virNodeDeviceFree;
+ virNodeDeviceGetXMLDesc;
+ virNodeDeviceGetName;
+ virNodeDeviceGetParent;
+ virNodeDeviceNumOfCaps;
+ virNodeDeviceListCaps;
} LIBVIRT_0.4.5;
LIBVIRT_0.6.0 {
global:
- virConnectRef;
- virDomainRef;
- virNetworkRef;
- virStoragePoolRef;
- virStorageVolRef;
- virNodeDeviceRef;
+ virConnectRef;
+ virDomainRef;
+ virNetworkRef;
+ virStoragePoolRef;
+ virStorageVolRef;
+ virNodeDeviceRef;
} LIBVIRT_0.5.0;
LIBVIRT_0.6.1 {
global:
- virFreeError;
- virSaveLastError;
- virNodeDeviceDettach;
- virNodeDeviceReAttach;
- virNodeDeviceReset;
- virDomainGetSecurityLabel;
- virNodeGetSecurityModel;
+ virFreeError;
+ virSaveLastError;
+ virNodeDeviceDettach;
+ virNodeDeviceReAttach;
+ virNodeDeviceReset;
+ virDomainGetSecurityLabel;
+ virNodeGetSecurityModel;
} LIBVIRT_0.6.0;
LIBVIRT_0.6.3 {
global:
- virNodeDeviceCreateXML;
- virNodeDeviceDestroy;
+ virNodeDeviceCreateXML;
+ virNodeDeviceDestroy;
} LIBVIRT_0.6.1;
LIBVIRT_0.6.4 {
global:
- virInterfaceGetConnect;
- virConnectNumOfInterfaces;
- virConnectListInterfaces;
- virInterfaceLookupByName;
- virInterfaceLookupByMACString;
- virInterfaceGetName;
- virInterfaceGetMACString;
- virInterfaceGetXMLDesc;
- virInterfaceRef;
- virInterfaceFree;
- virInterfaceDefineXML;
- virInterfaceUndefine;
- virInterfaceCreate;
- virInterfaceDestroy;
- virStorageVolCreateXMLFrom;
- virConnectDomainXMLFromNative;
- virConnectDomainXMLToNative;
+ virInterfaceGetConnect;
+ virConnectNumOfInterfaces;
+ virConnectListInterfaces;
+ virInterfaceLookupByName;
+ virInterfaceLookupByMACString;
+ virInterfaceGetName;
+ virInterfaceGetMACString;
+ virInterfaceGetXMLDesc;
+ virInterfaceRef;
+ virInterfaceFree;
+ virInterfaceDefineXML;
+ virInterfaceUndefine;
+ virInterfaceCreate;
+ virInterfaceDestroy;
+ virStorageVolCreateXMLFrom;
+ virConnectDomainXMLFromNative;
+ virConnectDomainXMLToNative;
} LIBVIRT_0.6.3;
LIBVIRT_0.7.0 {
global:
- virConnectNumOfDefinedInterfaces;
- virConnectListDefinedInterfaces;
+ virConnectNumOfDefinedInterfaces;
+ virConnectListDefinedInterfaces;
} LIBVIRT_0.6.4;
LIBVIRT_0.7.1 {
@@ -314,33 +314,33 @@ LIBVIRT_0.7.1 {
LIBVIRT_0.7.2 {
global:
- virStreamNew;
- virStreamRef;
- virStreamSend;
- virStreamRecv;
- virStreamSendAll;
- virStreamRecvAll;
- virStreamEventAddCallback;
- virStreamEventUpdateCallback;
- virStreamEventRemoveCallback;
- virStreamFinish;
- virStreamAbort;
- virStreamFree;
- virDomainMigrateToURI;
+ virStreamNew;
+ virStreamRef;
+ virStreamSend;
+ virStreamRecv;
+ virStreamSendAll;
+ virStreamRecvAll;
+ virStreamEventAddCallback;
+ virStreamEventUpdateCallback;
+ virStreamEventRemoveCallback;
+ virStreamFinish;
+ virStreamAbort;
+ virStreamFree;
+ virDomainMigrateToURI;
} LIBVIRT_0.7.1;
LIBVIRT_0.7.3 {
global:
- virConnectGetLibVersion;
- virConnectIsEncrypted;
- virConnectIsSecure;
- virDomainIsActive;
- virDomainIsPersistent;
- virNetworkIsActive;
- virNetworkIsPersistent;
- virStoragePoolIsActive;
- virStoragePoolIsPersistent;
- virInterfaceIsActive;
+ virConnectGetLibVersion;
+ virConnectIsEncrypted;
+ virConnectIsSecure;
+ virDomainIsActive;
+ virDomainIsPersistent;
+ virNetworkIsActive;
+ virNetworkIsPersistent;
+ virStoragePoolIsActive;
+ virStoragePoolIsPersistent;
+ virInterfaceIsActive;
} LIBVIRT_0.7.2;
LIBVIRT_0.7.5 {
@@ -355,32 +355,32 @@ LIBVIRT_0.7.7 {
virDomainDetachDeviceFlags;
virConnectBaselineCPU;
virDomainGetJobInfo;
- virDomainAbortJob;
+ virDomainAbortJob;
} LIBVIRT_0.7.5;
LIBVIRT_0.8.0 {
global:
- virStorageVolWipe;
+ virStorageVolWipe;
virDomainMigrateSetMaxDowntime;
virConnectDomainEventRegisterAny;
virConnectDomainEventDeregisterAny;
virDomainUpdateDeviceFlags;
- virConnectListNWFilters;
- virConnectNumOfNWFilters;
- virNWFilterLookupByName;
- virNWFilterLookupByUUID;
- virNWFilterLookupByUUIDString;
- virNWFilterFree;
- virNWFilterGetName;
- virNWFilterGetUUID;
- virNWFilterGetUUIDString;
- virNWFilterGetXMLDesc;
- virNWFilterRef;
- virNWFilterDefineXML;
- virNWFilterUndefine;
- virDomainManagedSave;
- virDomainHasManagedSaveImage;
- virDomainManagedSaveRemove;
+ virConnectListNWFilters;
+ virConnectNumOfNWFilters;
+ virNWFilterLookupByName;
+ virNWFilterLookupByUUID;
+ virNWFilterLookupByUUIDString;
+ virNWFilterFree;
+ virNWFilterGetName;
+ virNWFilterGetUUID;
+ virNWFilterGetUUIDString;
+ virNWFilterGetXMLDesc;
+ virNWFilterRef;
+ virNWFilterDefineXML;
+ virNWFilterUndefine;
+ virDomainManagedSave;
+ virDomainHasManagedSaveImage;
+ virDomainManagedSaveRemove;
virDomainSnapshotCreateXML;
virDomainSnapshotGetXMLDesc;
virDomainSnapshotNum;
--
1.7.7.5
12 years, 9 months
[libvirt] [PATCH] storage: Support different wiping algorithms
by Michal Privoznik
Currently, we support only filling a volume with zeroes on wiping.
However, it is not enough as data might still be readable by
experienced and equipped attacker. Many technical papers have been
written, therefore we should support other wiping algorithms.
---
Okay, this is not as complete as I'd like it. Wiping could take ages,
therefore we *want* it to be asynchronous. But that would mean:
1) Create new API to answer: "Are we done yet?"
2) Create event emitting system - like we have for domains
3) Combination of previous two
In fact, I've started writing events, but it turned out to be
huge and I am not even in a half yet. I need to find a way of
re-using event code we already have. But thats another day and
another patch set.
For those interested, take a look at Section 4.1.11 of DSS_PCI
requirements at [1].
1: https://www.pcisecuritystandards.org/documents/Virtualization_InfoSupp_v2...
configure.ac | 26 ++++++++++-
include/libvirt/libvirt.h.in | 24 ++++++++++
src/libvirt.c | 6 ++-
src/storage/storage_driver.c | 103 ++++++++++++++++++++++++++++++++++-------
tools/virsh.c | 41 +++++++++++++++-
tools/virsh.pod | 25 ++++++++++-
6 files changed, 201 insertions(+), 24 deletions(-)
diff --git a/configure.ac b/configure.ac
index 46a9129..fb5f669 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2500,7 +2500,31 @@ AM_CONDITIONAL([HAVE_LIBNL], [test "$have_libnl" = "yes"])
AC_SUBST([LIBNL_CFLAGS])
AC_SUBST([LIBNL_LIBS])
-
+dnl scrub program for different volume wiping algorithms
+
+AC_ARG_WITH([scrub],
+ AC_HELP_STRING([--with-scrub], [enable different volume wiping algorithms
+ @<:@default=check@:>@]),
+ [].
+ [with_scrub=check])
+
+if test "$with_scrub" != "no"; then
+ AC_PATH_PROG([SCRUB], [scrub])
+ if test -z "$SCRUB" ; then
+ if test "$with_scrub" = "check"; then
+ with_scrub=no
+ else
+ AC_MSG_ERROR([You must install the 'scrub' binary to enable
+ different volume wiping algorithms])
+ fi
+ else
+ with_scrub=yes
+ fi
+ if test "$with_scrub" = "yes"; then
+ AC_DEFINE_UNQUOTED([SCRUB], ["$SCRUB"],
+ [Location of the scrub program])
+ fi
+fi
# Only COPYING.LIB is under version control, yet COPYING
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index ad6fcce..caa9127 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -2118,6 +2118,30 @@ typedef enum {
VIR_STORAGE_VOL_DELETE_ZEROED = 1, /* Clear all data to zeros (slow) */
} virStorageVolDeleteFlags;
+typedef enum {
+ /* Keep this place for async flag. Currently,
+ * it is not implemented because of lack of
+ * events support within storage driver.
+ * VIR_STORAGE_VOL_WIPE_ASYNC = (1 << 0),
+ */
+ VIR_STORAGE_VOL_WIPE_ALG_NNSA = (1 << 1), /* 4-pass NNSA Policy Letter
+ NAP-14.1-C (XVI-8) */
+ VIR_STORAGE_VOL_WIPE_ALG_DOD = (1 << 2), /* 4-pass DoD 5220.22-M section
+ 8-306 procedure */
+ VIR_STORAGE_VOL_WIPE_ALG_BSI = (1 << 3), /* 9-pass method recommended by the
+ German Center of Security in
+ Information Technologies */
+ VIR_STORAGE_VOL_WIPE_ALG_GUTMANN = (1 << 4), /* The canonical 35-pass sequence */
+ VIR_STORAGE_VOL_WIPE_ALG_SCHNEIER = (1 << 5), /* 7-pass method described by
+ Bruce Schneier in "Applied
+ Cryptography" (1996) */
+ VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7 = (1 << 6), /* 7-pass random */
+
+ VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33 = (1 << 7), /* 33-pass random */
+
+ VIR_STORAGE_VOL_WIPE_ALG_RANDOM = (1 << 8), /* 1-pass random */
+} virStorageVolWipeFlags;
+
typedef struct _virStorageVolInfo virStorageVolInfo;
struct _virStorageVolInfo {
diff --git a/src/libvirt.c b/src/libvirt.c
index feb3ca6..c3b3665 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -12557,7 +12557,11 @@ error:
* @vol: pointer to storage volume
* @flags: future flags, use 0 for now
*
- * Ensure data previously on a volume is not accessible to future reads
+ * Ensure data previously on a volume is not accessible to future reads.
+ * When specifying wipe algorithm only one algorithm flag is allowed.
+ * Therefore if one wants to wipe a volume with say NNSA and DOD algorithms,
+ * he/she needs two subsequent calls. First with _ALG_NNSA flag, second
+ * with _ALG_DOD.
*
* Returns 0 on success, or -1 on error
*/
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index 8c2d6e1..f3a084a 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -1801,14 +1801,16 @@ out:
static int
-storageVolumeWipeInternal(virStorageVolDefPtr def)
+storageVolumeWipeInternal(virStorageVolDefPtr def,
+ unsigned int flags)
{
int ret = -1, fd = -1;
struct stat st;
char *writebuf = NULL;
size_t bytes_wiped = 0;
+ virCommandPtr cmd = NULL;
- VIR_DEBUG("Wiping volume with path '%s'", def->target.path);
+ VIR_DEBUG("Wiping volume with path '%s' flags %x", def->target.path, flags);
fd = open(def->target.path, O_RDWR);
if (fd == -1) {
@@ -1825,29 +1827,62 @@ storageVolumeWipeInternal(virStorageVolDefPtr def)
goto out;
}
- if (S_ISREG(st.st_mode) && st.st_blocks < (st.st_size / DEV_BSIZE)) {
- ret = storageVolumeZeroSparseFile(def, st.st_size, fd);
- } else {
-
- if (VIR_ALLOC_N(writebuf, st.st_blksize) != 0) {
- virReportOOMError();
+ if (flags) {
+ cmd = virCommandNew(SCRUB);
+ virCommandAddArg(cmd, "-f");
+ if (flags &VIR_STORAGE_VOL_WIPE_ALG_NNSA) {
+ virCommandAddArgList(cmd, "-p", "nnsa", NULL);
+ } else if (flags & VIR_STORAGE_VOL_WIPE_ALG_DOD) {
+ virCommandAddArgList(cmd, "-p", "dod", NULL);
+ } else if (flags & VIR_STORAGE_VOL_WIPE_ALG_BSI) {
+ virCommandAddArgList(cmd, "-p", "bsi", NULL);
+ } else if (flags & VIR_STORAGE_VOL_WIPE_ALG_GUTMANN) {
+ virCommandAddArgList(cmd, "-p", "gutmann", NULL);
+ } else if (flags & VIR_STORAGE_VOL_WIPE_ALG_SCHNEIER) {
+ virCommandAddArgList(cmd, "-p", "schneier", NULL);
+ } else if (flags & VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7) {
+ virCommandAddArgList(cmd, "-p", "pfitzner7", NULL);
+ } else if (flags & VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33) {
+ virCommandAddArgList(cmd, "-p", "pfitzner33", NULL);
+ } else if (flags & VIR_STORAGE_VOL_WIPE_ALG_RANDOM) {
+ virCommandAddArgList(cmd, "-p", "random", NULL);
+ } else {
+ virStorageReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unsupported flags %x"),
+ flags);
goto out;
}
- ret = storageWipeExtent(def,
- fd,
- 0,
- def->allocation,
- writebuf,
- st.st_blksize,
- &bytes_wiped);
+ virCommandAddArg(cmd, def->target.path);
+
+ if (virCommandRun(cmd, NULL) < 0)
+ goto out;
+
+ ret = 0;
+ } else {
+ if (S_ISREG(st.st_mode) && st.st_blocks < (st.st_size / DEV_BSIZE)) {
+ ret = storageVolumeZeroSparseFile(def, st.st_size, fd);
+ } else {
+
+ if (VIR_ALLOC_N(writebuf, st.st_blksize) != 0) {
+ virReportOOMError();
+ goto out;
+ }
+
+ ret = storageWipeExtent(def,
+ fd,
+ 0,
+ def->allocation,
+ writebuf,
+ st.st_blksize,
+ &bytes_wiped);
+ }
}
out:
+ virCommandFree(cmd);
VIR_FREE(writebuf);
-
VIR_FORCE_CLOSE(fd);
-
return ret;
}
@@ -1859,9 +1894,41 @@ storageVolumeWipe(virStorageVolPtr obj,
virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
virStoragePoolObjPtr pool = NULL;
virStorageVolDefPtr vol = NULL;
+ unsigned int alg = 0;
+ unsigned int supported_algs = 0;
+ unsigned int count = 0;
int ret = -1;
+ supported_algs = VIR_STORAGE_VOL_WIPE_ALG_NNSA |
+ VIR_STORAGE_VOL_WIPE_ALG_DOD |
+ VIR_STORAGE_VOL_WIPE_ALG_BSI |
+ VIR_STORAGE_VOL_WIPE_ALG_GUTMANN |
+ VIR_STORAGE_VOL_WIPE_ALG_SCHNEIER |
+ VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7 |
+ VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33 |
+ VIR_STORAGE_VOL_WIPE_ALG_RANDOM;
+
+#ifdef SCRUB
+ virCheckFlags(supported_algs, -1);
+#else
virCheckFlags(0, -1);
+#endif
+
+ alg = flags & supported_algs;
+ /* As we support only one algorithm in @flags,
+ * check if somebody didn't pass two or more
+ */
+ while (alg) {
+ count += alg & 1L;
+ alg >>= 1;
+ }
+
+ if (count > 1) {
+ virStorageReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("only one wiping algorithm "
+ "per call is allowed"));
+ return -1;
+ }
storageDriverLock(driver);
pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
@@ -1895,7 +1962,7 @@ storageVolumeWipe(virStorageVolPtr obj,
goto out;
}
- if (storageVolumeWipeInternal(vol) == -1) {
+ if (storageVolumeWipeInternal(vol, flags) == -1) {
goto out;
}
diff --git a/tools/virsh.c b/tools/virsh.c
index 0bc0519..3cb4109 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -10961,6 +10961,7 @@ static const vshCmdInfo info_vol_wipe[] = {
static const vshCmdOptDef opts_vol_wipe[] = {
{"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
{"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
+ {"algorithm", VSH_OT_STRING, 0, N_("perform selected wiping algorithm")},
{NULL, 0, 0, NULL}
};
@@ -10968,8 +10969,10 @@ static bool
cmdVolWipe(vshControl *ctl, const vshCmd *cmd)
{
virStorageVolPtr vol;
- bool ret = true;
+ bool ret = false;
const char *name;
+ const char *algorithm = NULL;
+ unsigned int flags = 0;
if (!vshConnectionUsability(ctl, ctl->conn))
return false;
@@ -10978,13 +10981,45 @@ cmdVolWipe(vshControl *ctl, const vshCmd *cmd)
return false;
}
- if (virStorageVolWipe(vol, 0) == 0) {
+ if (vshCommandOptString(cmd, "algorithm", &algorithm) < 0) {
+ vshError(ctl, "%s", _("missing argument"));
+ goto out;
+ }
+
+ if (algorithm) {
+ if (STREQ(algorithm, "nnsa"))
+ flags |= VIR_STORAGE_VOL_WIPE_ALG_NNSA;
+ else if (STREQ(algorithm, "dod"))
+ flags |= VIR_STORAGE_VOL_WIPE_ALG_DOD;
+ else if (STREQ(algorithm, "bsi"))
+ flags |= VIR_STORAGE_VOL_WIPE_ALG_BSI;
+ else if (STREQ(algorithm, "gutmann"))
+ flags |= VIR_STORAGE_VOL_WIPE_ALG_GUTMANN;
+ else if (STREQ(algorithm, "schneier"))
+ flags |= VIR_STORAGE_VOL_WIPE_ALG_SCHNEIER;
+ else if (STREQ(algorithm, "pfitzner7"))
+ flags |= VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7;
+ else if (STREQ(algorithm, "pfitzner33"))
+ flags |= VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33;
+ else if (STREQ(algorithm, "random"))
+ flags |= VIR_STORAGE_VOL_WIPE_ALG_RANDOM;
+ else {
+ vshError(ctl, _("Unsupported algorithm '%s'"),
+ algorithm);
+ goto out;
+ }
+ }
+
+ if (virStorageVolWipe(vol, flags) == 0) {
vshPrint(ctl, _("Vol %s wiped\n"), name);
} else {
vshError(ctl, _("Failed to wipe vol %s"), name);
- ret = false;
+ goto out;
}
+ ret = true;
+
+out:
virStorageVolFree(vol);
return ret;
}
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 138f886..d96e8c8 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -1912,12 +1912,35 @@ I<vol-name-or-key-or-path> is the name or key or path of the volume to wipe.
I<--offset> is the position in the storage volume at which to start reading
the data. I<--length> is an upper bound of the amount of data to be downloaded.
-=item B<vol-wipe> [I<--pool> I<pool-or-uuid>] I<vol-name-or-key-or-path>
+=item B<vol-wipe> [I<--pool> I<pool-or-uuid>] [I<--algorithm> I<algorithm>]
+I<vol-name-or-key-or-path>
Wipe a volume, ensure data previously on the volume is not accessible to
future reads. I<--pool> I<pool-or-uuid> is the name or UUID of the storage
pool the volume is in.
I<vol-name-or-key-or-path> is the name or key or path of the volume to wipe.
+It is possible to choose different wiping algorithms instead of re-writing
+volume with zeroes. This can be done via I<--algorithm> switch.
+
+B<Supported algorithms>
+ nnsa - 4-pass NNSA Policy Letter NAP-14.1-C (XVI-8) for
+ sanitizing removable and non-removable hard disks:
+ random(x2), 0x00, verify.
+ dod - 4-pass DoD 5220.22-M section 8-306 procedure for
+ sanitizing removeable and non-removeable rigid
+ disks: random, 0x00, 0xff, verify.
+ bsi - 9-pass method recommended by the German Center of
+ Security in Information Technologies
+ (http://www.bsi.bund.de): 0xff, 0xfe, 0xfd, 0xfb,
+ 0xf7, 0xef, 0xdf, 0xbf, 0x7f.
+ gutmann - The canonical 35-pass sequence described in
+ Gutmann's paper.
+ schneier - 7-pass method described by Bruce Schneier in
+ "Applied Cryptography" (1996): 0x00, 0xff,
+ random(x5).
+ pfitzner7 - Roy Pfitzner's 7-random-pass method: random(x7).
+ pfitzner33 - Roy Pfitzner's 33-random-pass method: random(x33).
+ random - 1-pass pattern: random(x1).
=item B<vol-dumpxml> [I<--pool> I<pool-or-uuid>] I<vol-name-or-key-or-path>
--
1.7.3.4
12 years, 9 months
[libvirt] Using Libvirt to change the bridge a virtual network card of a running vm is connected to
by Ralf Spenneberg
Hi there,
we are using libvirt to manage our VMs. We have several VMs connected to
different bridges on the same physical KVM host. We need to change the
bridge a virtual machine is connected to once in a while. Currently we
are just using brctl to do that. Since this needs to be done over the
network we would like to use the Libvirtd. Currently this does not seem
possible. We have not found any interface or function within the libvirt
library to implement this in a live VM. Only shutdown VMs may be changed
via editing the XML representation.
Is there any reason for that? Could such a function be easily
implemented?
Everything but the source bridge would stay the same. It works fine
manually via brctl.
Any thoughts?
Ralf Spenneberg
12 years, 9 months
[libvirt] [PATCH] docs: fix virsh man page
by Eric Blake
Typo introduced in commit 4e9953a.
* tools/virsh.pod (snapshot-create): Fix pod error.
---
Pushing under the trivial rule.
It bothers me that I have to use RHEL 5 to catch obvious errors,
and that newer perl is too lax to flag bugs like this.
tools/virsh.pod | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/tools/virsh.pod b/tools/virsh.pod
index b6962cf..e1d8774 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -2046,7 +2046,7 @@ used to represent properties of snapshots.
=over 4
=item B<snapshot-create> I<domain> [I<xmlfile>] {[I<--redefine> [I<--current>]]
-| [I<--no-metadata>] [I<--halt>] [I<--disk-only>] [I<--reuse-external]
+| [I<--no-metadata>] [I<--halt>] [I<--disk-only>] [I<--reuse-external>]
[I<--quiesce>]}
Create a snapshot for domain I<domain> with the properties specified in
--
1.7.7.6
12 years, 9 months
[libvirt] [PATCH libvirt] Add missing virGetGroupName()
by Marc-André Lureau
Add missing function if !HAVE_GETPWUID_R.
---
src/util/util.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/src/util/util.c b/src/util/util.c
index c00c2f9..33bcf29 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -2471,6 +2471,15 @@ virSetUIDGID(uid_t uid ATTRIBUTE_UNUSED,
"%s", _("virSetUIDGID is not available"));
return -1;
}
+
+char *
+virGetGroupName(gid_t gid ATTRIBUTE_UNUSED)
+{
+ virUtilError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("virGetGroupName is not available"));
+
+ return NULL;
+}
#endif /* HAVE_GETPWUID_R */
--
1.7.7.5
12 years, 9 months
[libvirt] [PATCH] storage: Fix any VolLookupByPath if we have an empty logical pool
by Cole Robinson
On F16 at least, empty volume groups don't have a directory under /dev.
The directory only appears once a logical volume is created.
This tickles some behavior in BackendStablePath which ends with
libvirt sleeping for 5 seconds while waiting for the directory to appear.
This causes all sorts of problems for the virStorageVolLookupByPath API
which virtinst uses, even if trying to resolve a path that is independent
of the logical pool.
In reality we don't even need to do that checking since logical pools
always have a stable target path. Short circuit the polling in that
case.
Fixes bug 782261
---
src/storage/storage_backend.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index d7394e0..306e487 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -1347,6 +1347,10 @@ virStorageBackendStablePath(virStoragePoolObjPtr pool,
if (!STRPREFIX(pool->def->target.path, "/dev"))
goto ret_strdup;
+ /* Logical pools are under /dev but already have stable paths */
+ if (pool->def->type == VIR_STORAGE_POOL_LOGICAL)
+ goto ret_strdup;
+
/* We loop here because /dev/disk/by-{id,path} may not have existed
* before we started this operation, so we have to give it some time to
* get created.
--
1.7.7.5
12 years, 9 months
[libvirt] [PATCH] Replace hashing algorithm with murmurhash
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
Recent discussions have illustrated the potential for DOS attacks
with the hash table implementations used by most languages and
libraries.
https://lwn.net/Articles/474912/
libvirt has an internal hash table impl, and uses hash tables for
a variety of purposes. The hash key generation code is pretty
simple and thus not strongly collision resistant.
This patch replaces the current libvirt hash key generator with
the (public domain) Murmurhash3 code. In addition every hash
table now gets a random seed value which is used to perturb the
hashing code. This should make it impossible to mount any
practical attack against libvirt hashing code.
* src/Makefile.am: Add virhashcode.[ch]
* src/util/util.c: Make virRandom() return a fixed 32 bit
integer value.
* src/util/hash.c, src/util/hash.h, src/util/cgroup.c: Replace
hash code generation with a call to virHashCodeGen()
* src/util/virhashcode.h, src/util/virhashcode.c: Add a new
virHashCodeGen() API using the Murmurhash3 algorithm.
---
src/Makefile.am | 1 +
src/util/cgroup.c | 6 ++-
src/util/hash.c | 24 ++++------
src/util/hash.h | 7 ++-
src/util/util.c | 4 +-
src/util/virhashcode.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++
src/util/virhashcode.h | 35 +++++++++++++
7 files changed, 181 insertions(+), 21 deletions(-)
create mode 100644 src/util/virhashcode.c
create mode 100644 src/util/virhashcode.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 0a1221a..dd5acc4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -89,6 +89,7 @@ UTIL_SOURCES = \
util/virpidfile.c util/virpidfile.h \
util/xml.c util/xml.h \
util/virterror.c util/virterror_internal.h \
+ util/virhashcode.c util/virhashcode.h \
util/virkeycode.c util/virkeycode.h \
util/virkeymaps.h \
util/virnetdev.h util/virnetdev.c \
diff --git a/src/util/cgroup.c b/src/util/cgroup.c
index 25f2691..7623264 100644
--- a/src/util/cgroup.c
+++ b/src/util/cgroup.c
@@ -33,6 +33,7 @@
#include "logging.h"
#include "virfile.h"
#include "hash.h"
+#include "virhashcode.h"
#define CGROUP_MAX_VAL 512
@@ -1636,9 +1637,10 @@ cleanup:
}
-static unsigned long virCgroupPidCode(const void *name)
+static int32_t virCgroupPidCode(const void *name, int32_t seed)
{
- return (unsigned long)name;
+ unsigned long pid = (unsigned long)name;
+ return virHashCodeGen(&pid, sizeof(pid), seed);
}
static bool virCgroupPidEqual(const void *namea, const void *nameb)
{
diff --git a/src/util/hash.c b/src/util/hash.c
index 665bcce..e765a6c 100644
--- a/src/util/hash.c
+++ b/src/util/hash.c
@@ -28,6 +28,8 @@
#include "hash.h"
#include "memory.h"
#include "logging.h"
+#include "virhashcode.h"
+#include "util.h"
#define VIR_FROM_THIS VIR_FROM_NONE
@@ -57,6 +59,7 @@ struct _virHashEntry {
*/
struct _virHashTable {
virHashEntryPtr *table;
+ uint32_t seed;
int size;
int nbElems;
/* True iff we are iterating over hash entries. */
@@ -70,20 +73,11 @@ struct _virHashTable {
virHashKeyFree keyFree;
};
-static unsigned long virHashStrCode(const void *name)
+
+
+static int32_t virHashStrCode(const void *name, int32_t seed)
{
- const char *str = name;
- unsigned long value = 0L;
- char ch;
-
- if (str != NULL) {
- value += 30 * (*str);
- while ((ch = *str++) != 0) {
- value =
- value ^ ((value << 5) + (value >> 3) + (unsigned long) ch);
- }
- }
- return value;
+ return virHashCodeGen(name, strlen(name), seed);
}
static bool virHashStrEqual(const void *namea, const void *nameb)
@@ -101,11 +95,10 @@ static void virHashStrFree(void *name)
VIR_FREE(name);
}
-
static unsigned long
virHashComputeKey(virHashTablePtr table, const void *name)
{
- unsigned long value = table->keyCode(name);
+ uint32_t value = table->keyCode(name, table->seed);
return (value % table->size);
}
@@ -139,6 +132,7 @@ virHashTablePtr virHashCreateFull(int size,
return NULL;
}
+ table->seed = virRandom(INT32_MAX);
table->size = size;
table->nbElems = 0;
table->dataFree = dataFree;
diff --git a/src/util/hash.h b/src/util/hash.h
index 1ba12b9..c415844 100644
--- a/src/util/hash.h
+++ b/src/util/hash.h
@@ -55,12 +55,15 @@ typedef int (*virHashSearcher) (const void *payload, const void *name,
/**
* virHashKeyCode:
* @name: the hash key
+ * @seed: random seed
*
- * Compute the hash code corresponding to the key @name
+ * Compute the hash code corresponding to the key @name, using
+ * @seed to perturb the hashing algorithm
*
* Returns the hash code
*/
-typedef unsigned long (*virHashKeyCode)(const void *name);
+typedef int32_t (*virHashKeyCode)(const void *name,
+ int32_t seed);
/**
* virHashKeyEqual:
* @namea: the first hash key
diff --git a/src/util/util.c b/src/util/util.c
index 8663c4d..c8588b5 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -2115,7 +2115,7 @@ int virRandomInitialize(unsigned int seed)
return 0;
}
-int virRandom(int max)
+int32_t virRandom(int32_t max)
{
int32_t ret;
@@ -2123,7 +2123,7 @@ int virRandom(int max)
random_r(&randomData, &ret);
virMutexUnlock(&randomLock);
- return (int) ((double)max * ((double)ret / (double)RAND_MAX));
+ return (int32_t) ((double)max * ((double)ret / (double)RAND_MAX));
}
diff --git a/src/util/virhashcode.c b/src/util/virhashcode.c
new file mode 100644
index 0000000..50b46f4
--- /dev/null
+++ b/src/util/virhashcode.c
@@ -0,0 +1,125 @@
+/*
+ * virhashcode.c: hash code generation
+ *
+ * Copyright (C) 2012 Red Hat, 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
+ *
+ * The hash code generation is based on the public domain MurmurHash3 from Austin Appleby:
+ * http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
+ *
+ * We use only the 32 bit variant because the 2 produce different result while
+ * we need to produce the same result regardless of the architecture as
+ * clients can be both 64 or 32 bit at the same time.
+ */
+
+#include <config.h>
+
+#include "virhashcode.h"
+
+static uint32_t rotl(uint32_t x, int8_t r)
+{
+ return (x << r) | (x >> (32 - r));
+}
+
+/* slower than original but is endian neutral and handles platforms that
+ * do only aligned reads */
+__attribute__((always_inline))
+static uint32_t getblock(const uint8_t *p, int i)
+{
+ uint32_t r;
+ size_t size = sizeof(uint32_t);
+
+ memcpy(&r, &p[i * size], size);
+
+ return le32toh(r);
+}
+
+/*
+ * Finalization mix - force all bits of a hash block to avalanche
+ */
+__attribute__((always_inline))
+static uint32_t fmix(uint32_t h)
+{
+ h ^= h >> 16;
+ h *= 0x85ebca6b;
+ h ^= h >> 13;
+ h *= 0xc2b2ae35;
+ h ^= h >> 16;
+
+ return h;
+}
+
+
+uint32_t virHashCodeGen(const void *key, size_t len, uint32_t seed)
+{
+ const uint8_t *blocks;
+ const uint8_t *tail;
+ size_t nblocks;
+ uint32_t h1;
+ uint32_t k1;
+ uint32_t c1;
+ uint32_t c2;
+ size_t i;
+
+ blocks = (const uint8_t *)key;
+ nblocks = len / 4;
+ h1 = seed;
+ c1 = 0xcc9e2d51;
+ c2 = 0x1b873593;
+
+ /* body */
+
+ for (i = 0; i < nblocks; i++) {
+
+ k1 = getblock(blocks, i);
+
+ k1 *= c1;
+ k1 = rotl(k1, 15);
+ k1 *= c2;
+
+ h1 ^= k1;
+ h1 = rotl(h1, 13);
+ h1 = h1 * 5 + 0xe6546b64;
+ }
+
+ /* tail */
+
+ tail = (const uint8_t *)key + nblocks * 4;
+
+ k1 = 0;
+
+ switch (len & 3) {
+ case 3:
+ k1 ^= tail[2] << 16;
+ case 2:
+ k1 ^= tail[1] << 8;
+ case 1:
+ k1 ^= tail[0];
+ k1 *= c1;
+ k1 = rotl(k1, 15);
+ k1 *= c2;
+ h1 ^= k1;
+ default:
+ break;
+ }
+
+ /* finalization */
+
+ h1 ^= len;
+ h1 = fmix(h1);
+
+ return h1;
+}
diff --git a/src/util/virhashcode.h b/src/util/virhashcode.h
new file mode 100644
index 0000000..867e04e
--- /dev/null
+++ b/src/util/virhashcode.h
@@ -0,0 +1,35 @@
+/*
+ * virhashcode.h: hash code generation
+ *
+ * Copyright (C) 2012 Red Hat, 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
+ *
+ * The hash code generation is based on the public domain MurmurHash3 from Austin Appleby:
+ * http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
+ *
+ * We use only the 32 bit variant because the 2 produce different result while
+ * we need to produce the same result regardless of the architecture as
+ * clients can be both 64 or 32 bit at the same time.
+ */
+
+#ifndef __VIR_HASH_CODE_H__
+# define __VIR_HASH_CODE_H__
+
+# include "internal.h"
+
+extern uint32_t virHashCodeGen(const void *key, size_t len, uint32_t seed);
+
+#endif /* __VIR_HASH_CODE_H__ */
--
1.7.7.5
12 years, 9 months