[libvirt] [PATCH 0/3] Prohibit passing all clear cpumap for vcpupin/emulatorpin

*** NONE *** Osier Yang (3): util: Add a helper to check if all bits of a bitmap are clear qemu: Error out if the bitmap for pinning is all clear virsh: Prohibit all clear cpumap src/libvirt_private.syms | 1 + src/qemu/qemu_driver.c | 12 ++++++++++++ src/util/virbitmap.c | 30 ++++++++++++++++++++++++++++++ src/util/virbitmap.h | 3 +++ tools/virsh-domain.c | 35 ++++++++++++++++++++++++++++++----- 5 files changed, 76 insertions(+), 5 deletions(-) -- 1.8.1.4

--- src/libvirt_private.syms | 1 + src/util/virbitmap.c | 30 ++++++++++++++++++++++++++++++ src/util/virbitmap.h | 3 +++ 3 files changed, 34 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 96eea0a..35ac957 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1048,6 +1048,7 @@ virBitmapEqual; virBitmapFormat; virBitmapFree; virBitmapGetBit; +virBitmapIsAllClear; virBitmapIsAllSet; virBitmapNew; virBitmapNewCopy; diff --git a/src/util/virbitmap.c b/src/util/virbitmap.c index 21509ac..99a8572 100644 --- a/src/util/virbitmap.c +++ b/src/util/virbitmap.c @@ -591,6 +591,36 @@ bool virBitmapIsAllSet(virBitmapPtr bitmap) } /** + * virBitmapIsAllClear: + * @bitmap: the bitmap to check + * + * check if all bits in @bitmap are clear + */ +bool virBitmapIsAllClear(virBitmapPtr bitmap) +{ + int i; + int unusedBits; + size_t sz; + + unusedBits = bitmap->map_len * VIR_BITMAP_BITS_PER_UNIT - bitmap->max_bit; + + sz = bitmap->map_len; + if (unusedBits > 0) + sz--; + + for (i = 0; i < sz; i++) + if (bitmap->map[i] != 0) + return false; + + if (unusedBits > 0) { + if ((bitmap->map[sz] & ((1UL << (VIR_BITMAP_BITS_PER_UNIT - unusedBits)) - 1))) + return false; + } + + return true; +} + +/** * virBitmapNextSetBit: * @bitmap: the bitmap * @pos: the position after which to search for a set bit diff --git a/src/util/virbitmap.h b/src/util/virbitmap.h index 044c7a6..b682523 100644 --- a/src/util/virbitmap.h +++ b/src/util/virbitmap.h @@ -100,6 +100,9 @@ void virBitmapClearAll(virBitmapPtr bitmap) bool virBitmapIsAllSet(virBitmapPtr bitmap) ATTRIBUTE_NONNULL(1); +bool virBitmapIsAllClear(virBitmapPtr bitmap) + ATTRIBUTE_NONNULL(1); + ssize_t virBitmapNextSetBit(virBitmapPtr bitmap, ssize_t pos) ATTRIBUTE_NONNULL(1); -- 1.8.1.4

On 04/02/2013 01:42 AM, Osier Yang wrote:
--- src/libvirt_private.syms | 1 + src/util/virbitmap.c | 30 ++++++++++++++++++++++++++++++ src/util/virbitmap.h | 3 +++ 3 files changed, 34 insertions(+)
Since there already is a "virBitmapIsAllSet()" - why isn't it used? I see callers which do "if (virBitmapIsAllSet(...)" and "if (!virBitmapIsAllSet(...)". If you're going to have a AllClear(), then why not change those ! callers to use AllClear()... I only wonder about the last comparison - it's the "-1" logic that throws me off especially since the IsAllSet() code is doing a comparison. It also stands to reason that tests/virbitmaptest.c could add new tests to ensure you did get the logic right. John
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 96eea0a..35ac957 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1048,6 +1048,7 @@ virBitmapEqual; virBitmapFormat; virBitmapFree; virBitmapGetBit; +virBitmapIsAllClear; virBitmapIsAllSet; virBitmapNew; virBitmapNewCopy; diff --git a/src/util/virbitmap.c b/src/util/virbitmap.c index 21509ac..99a8572 100644 --- a/src/util/virbitmap.c +++ b/src/util/virbitmap.c @@ -591,6 +591,36 @@ bool virBitmapIsAllSet(virBitmapPtr bitmap) }
/** + * virBitmapIsAllClear: + * @bitmap: the bitmap to check + * + * check if all bits in @bitmap are clear + */ +bool virBitmapIsAllClear(virBitmapPtr bitmap) +{ + int i; + int unusedBits; + size_t sz; + + unusedBits = bitmap->map_len * VIR_BITMAP_BITS_PER_UNIT - bitmap->max_bit; + + sz = bitmap->map_len; + if (unusedBits > 0) + sz--; + + for (i = 0; i < sz; i++) + if (bitmap->map[i] != 0) + return false; + + if (unusedBits > 0) { + if ((bitmap->map[sz] & ((1UL << (VIR_BITMAP_BITS_PER_UNIT - unusedBits)) - 1))) + return false; + } + + return true; +} + +/** * virBitmapNextSetBit: * @bitmap: the bitmap * @pos: the position after which to search for a set bit diff --git a/src/util/virbitmap.h b/src/util/virbitmap.h index 044c7a6..b682523 100644 --- a/src/util/virbitmap.h +++ b/src/util/virbitmap.h @@ -100,6 +100,9 @@ void virBitmapClearAll(virBitmapPtr bitmap) bool virBitmapIsAllSet(virBitmapPtr bitmap) ATTRIBUTE_NONNULL(1);
+bool virBitmapIsAllClear(virBitmapPtr bitmap) + ATTRIBUTE_NONNULL(1); + ssize_t virBitmapNextSetBit(virBitmapPtr bitmap, ssize_t pos) ATTRIBUTE_NONNULL(1);

On Tue, Apr 02, 2013 at 06:52:22AM -0400, John Ferlan wrote:
On 04/02/2013 01:42 AM, Osier Yang wrote:
--- src/libvirt_private.syms | 1 + src/util/virbitmap.c | 30 ++++++++++++++++++++++++++++++ src/util/virbitmap.h | 3 +++ 3 files changed, 34 insertions(+)
Since there already is a "virBitmapIsAllSet()" - why isn't it used? I see callers which do "if (virBitmapIsAllSet(...)" and "if (!virBitmapIsAllSet(...)".
If you're going to have a AllClear(), then why not change those ! callers to use AllClear()...
!virBitmapIsAllSet() is not the same as virBitmapIsAllClear(). !virBitmapIsAllSet() allows for [0 -> (n-1)] bits to be set, whereas virBitmapIsAllClear() only allows for 0 bits to be set. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 02/04/13 18:52, John Ferlan wrote:
On 04/02/2013 01:42 AM, Osier Yang wrote:
--- src/libvirt_private.syms | 1 + src/util/virbitmap.c | 30 ++++++++++++++++++++++++++++++ src/util/virbitmap.h | 3 +++ 3 files changed, 34 insertions(+)
Since there already is a "virBitmapIsAllSet()" - why isn't it used? I see callers which do "if (virBitmapIsAllSet(...)" and "if (!virBitmapIsAllSet(...)".
I want to check if the bitmap is all zero. Obviously !virBitmapIsAllSet can't do it.
If you're going to have a AllClear(), then why not change those ! callers to use AllClear()...
I only wonder about the last comparison - it's the "-1" logic that throws me off especially since the IsAllSet() code is doing a comparison.
It also stands to reason that tests/virbitmaptest.c could add new tests to ensure you did get the logic right.
Agreed. I didn't notice this. Will add. Osier

On 04/01/2013 11:42 PM, Osier Yang wrote:
--- src/libvirt_private.syms | 1 + src/util/virbitmap.c | 30 ++++++++++++++++++++++++++++++ src/util/virbitmap.h | 3 +++ 3 files changed, 34 insertions(+)
+bool virBitmapIsAllClear(virBitmapPtr bitmap) +{ + int i; + int unusedBits; + size_t sz; + + unusedBits = bitmap->map_len * VIR_BITMAP_BITS_PER_UNIT - bitmap->max_bit; + + sz = bitmap->map_len; + if (unusedBits > 0) + sz--; + + for (i = 0; i < sz; i++) + if (bitmap->map[i] != 0) + return false; + + if (unusedBits > 0) { + if ((bitmap->map[sz] & ((1UL << (VIR_BITMAP_BITS_PER_UNIT - unusedBits)) - 1))) + return false;
You are being careful to avoid assuming any state about the bits in the tail beyond the bitmap size. But I thought our code was already careful to ensure that the tail bits are always 0. Therefore, you should be able to just check that the entire bitmap->map is 0, without special-casing the tail. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

For both "live" and "config" changes of vcpupin and emulatorpin, an all clear bitmap doesn't make sense, and it can just cause corruptions. E.g (similar for emulatorpin). % virsh vcpupin hame 0 8,^8 --config % virsh vcpupin hame VCPU: CPU Affinity ---------------------------------- 0: 1: 0-63 2: 0-63 3: 0-63 % virsh dumpxml hame |grep cpuset <vcpupin vcpu='0' cpuset=''/> % virsh start ham error: Failed to start domain hame error: An error occurred, but the cause is unknown --- src/qemu/qemu_driver.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 96bf235..c6dc882 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3892,6 +3892,12 @@ qemuDomainPinVcpuFlags(virDomainPtr dom, if (!pcpumap) goto cleanup; + if (virBitmapIsAllClear(pcpumap)) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Empty cpu list for pinning")); + goto cleanup; + } + /* pinning to all physical cpus means resetting, * so check if we can reset setting. */ @@ -4161,6 +4167,12 @@ qemuDomainPinEmulator(virDomainPtr dom, if (!pcpumap) goto cleanup; + if (virBitmapIsAllClear(pcpumap)) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Empty cpu list for pinning")); + goto cleanup; + } + /* pinning to all physical cpus means resetting, * so check if we can reset setting. */ -- 1.8.1.4

On 04/02/2013 01:42 AM, Osier Yang wrote:
For both "live" and "config" changes of vcpupin and emulatorpin, an all clear bitmap doesn't make sense, and it can just cause corruptions. E.g (similar for emulatorpin).
% virsh vcpupin hame 0 8,^8 --config
% virsh vcpupin hame VCPU: CPU Affinity ---------------------------------- 0: 1: 0-63 2: 0-63 3: 0-63
% virsh dumpxml hame |grep cpuset <vcpupin vcpu='0' cpuset=''/>
% virsh start ham error: Failed to start domain hame error: An error occurred, but the cause is unknown --- src/qemu/qemu_driver.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
ACK - nit - provide the "new" error (also your virsh start line is missing the 'e' on ham... John

This prohibits all clear cpumap eariler in virsh, for both vcpupin and emulatorpin. --- tools/virsh-domain.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 965f92c..8d3d63f 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -5552,6 +5552,20 @@ cleanup: } static bool +vshIsCpumapAllClear(const unsigned char *cpumap, + int maxcpu) +{ + int i; + + for (i = 0; i < maxcpu; i++) { + if (VIR_CPU_USED(cpumap, i)) + return false; + } + + return true; +} + +static bool cmdVcpuPin(vshControl *ctl, const vshCmd *cmd) { virDomainInfo info; @@ -5620,7 +5634,7 @@ cmdVcpuPin(vshControl *ctl, const vshCmd *cmd) cpumaplen = VIR_CPU_MAPLEN(maxcpu); - /* Query mode: show CPU affinity information then exit.*/ + /* Query mode: show CPU affinity information then exit. */ if (query) { /* When query mode and neither "live", "config" nor "current" * is specified, set VIR_DOMAIN_AFFECT_CURRENT as flags */ @@ -5649,10 +5663,15 @@ cmdVcpuPin(vshControl *ctl, const vshCmd *cmd) goto cleanup; } - /* Pin mode: pinning specified vcpu to specified physical cpus*/ + /* Pin mode: pinning specified vcpu to specified physical cpus. */ if (!(cpumap = vshParseCPUList(ctl, cpulist, maxcpu, cpumaplen))) goto cleanup; + if (vshIsCpumapAllClear(cpumap, maxcpu)) { + vshError(ctl, "%s", _("No CPU specified")); + goto cleanup; + } + if (flags == -1) { if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0) goto cleanup; @@ -5755,10 +5774,11 @@ cmdEmulatorPin(vshControl *ctl, const vshCmd *cmd) cpumaplen = VIR_CPU_MAPLEN(maxcpu); - /* Query mode: show CPU affinity information then exit.*/ + /* Query mode: show CPU affinity information then exit. */ if (query) { /* When query mode and neither "live", "config" nor "current" - * is specified, set VIR_DOMAIN_AFFECT_CURRENT as flags */ + * is specified, set VIR_DOMAIN_AFFECT_CURRENT as flags. + */ if (flags == -1) flags = VIR_DOMAIN_AFFECT_CURRENT; @@ -5775,10 +5795,15 @@ cmdEmulatorPin(vshControl *ctl, const vshCmd *cmd) goto cleanup; } - /* Pin mode: pinning emulator threads to specified physical cpus*/ + /* Pin mode: pinning emulator threads to specified physical cpus. */ if (!(cpumap = vshParseCPUList(ctl, cpulist, maxcpu, cpumaplen))) goto cleanup; + if (vshIsCpumapAllClear(cpumap, maxcpu)) { + vshError(ctl, "%s", _("No CPU is specified")); + goto cleanup; + } + if (flags == -1) flags = VIR_DOMAIN_AFFECT_LIVE; -- 1.8.1.4

On 04/02/2013 01:42 AM, Osier Yang wrote:
This prohibits all clear cpumap eariler in virsh, for both vcpupin and emulatorpin. --- tools/virsh-domain.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 965f92c..8d3d63f 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -5552,6 +5552,20 @@ cleanup: }
static bool +vshIsCpumapAllClear(const unsigned char *cpumap, + int maxcpu) +{ + int i; + + for (i = 0; i < maxcpu; i++) { + if (VIR_CPU_USED(cpumap, i)) + return false; + } + + return true; +} + +static bool cmdVcpuPin(vshControl *ctl, const vshCmd *cmd) { virDomainInfo info; @@ -5620,7 +5634,7 @@ cmdVcpuPin(vshControl *ctl, const vshCmd *cmd)
cpumaplen = VIR_CPU_MAPLEN(maxcpu);
- /* Query mode: show CPU affinity information then exit.*/ + /* Query mode: show CPU affinity information then exit. */ if (query) { /* When query mode and neither "live", "config" nor "current" * is specified, set VIR_DOMAIN_AFFECT_CURRENT as flags */ @@ -5649,10 +5663,15 @@ cmdVcpuPin(vshControl *ctl, const vshCmd *cmd) goto cleanup; }
- /* Pin mode: pinning specified vcpu to specified physical cpus*/ + /* Pin mode: pinning specified vcpu to specified physical cpus. */ if (!(cpumap = vshParseCPUList(ctl, cpulist, maxcpu, cpumaplen))) goto cleanup;
+ if (vshIsCpumapAllClear(cpumap, maxcpu)) { + vshError(ctl, "%s", _("No CPU specified")); + goto cleanup; + } + if (flags == -1) { if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0) goto cleanup; @@ -5755,10 +5774,11 @@ cmdEmulatorPin(vshControl *ctl, const vshCmd *cmd)
cpumaplen = VIR_CPU_MAPLEN(maxcpu);
- /* Query mode: show CPU affinity information then exit.*/ + /* Query mode: show CPU affinity information then exit. */ if (query) { /* When query mode and neither "live", "config" nor "current" - * is specified, set VIR_DOMAIN_AFFECT_CURRENT as flags */ + * is specified, set VIR_DOMAIN_AFFECT_CURRENT as flags. + */ if (flags == -1) flags = VIR_DOMAIN_AFFECT_CURRENT;
@@ -5775,10 +5795,15 @@ cmdEmulatorPin(vshControl *ctl, const vshCmd *cmd) goto cleanup; }
- /* Pin mode: pinning emulator threads to specified physical cpus*/ + /* Pin mode: pinning emulator threads to specified physical cpus. */ if (!(cpumap = vshParseCPUList(ctl, cpulist, maxcpu, cpumaplen))) goto cleanup;
+ if (vshIsCpumapAllClear(cpumap, maxcpu)) { + vshError(ctl, "%s", _("No CPU is specified")); + goto cleanup; + } + if (flags == -1) flags = VIR_DOMAIN_AFFECT_LIVE;
Unlike the virReportError() which provides the function trace - how would one know which of the two functions had the error here? OK other than looking at the code and noting one error has an "is" verb and the other doesn't... One message could indicate "No domain vCPU affinity" while the other could indicate "No domain emulator affinity"... John

On 02/04/13 18:53, John Ferlan wrote:
On 04/02/2013 01:42 AM, Osier Yang wrote:
This prohibits all clear cpumap eariler in virsh, for both vcpupin and emulatorpin. --- tools/virsh-domain.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 965f92c..8d3d63f 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -5552,6 +5552,20 @@ cleanup: }
static bool +vshIsCpumapAllClear(const unsigned char *cpumap, + int maxcpu) +{ + int i; + + for (i = 0; i < maxcpu; i++) { + if (VIR_CPU_USED(cpumap, i)) + return false; + } + + return true; +} + +static bool cmdVcpuPin(vshControl *ctl, const vshCmd *cmd) { virDomainInfo info; @@ -5620,7 +5634,7 @@ cmdVcpuPin(vshControl *ctl, const vshCmd *cmd)
cpumaplen = VIR_CPU_MAPLEN(maxcpu);
- /* Query mode: show CPU affinity information then exit.*/ + /* Query mode: show CPU affinity information then exit. */ if (query) { /* When query mode and neither "live", "config" nor "current" * is specified, set VIR_DOMAIN_AFFECT_CURRENT as flags */ @@ -5649,10 +5663,15 @@ cmdVcpuPin(vshControl *ctl, const vshCmd *cmd) goto cleanup; }
- /* Pin mode: pinning specified vcpu to specified physical cpus*/ + /* Pin mode: pinning specified vcpu to specified physical cpus. */ if (!(cpumap = vshParseCPUList(ctl, cpulist, maxcpu, cpumaplen))) goto cleanup;
+ if (vshIsCpumapAllClear(cpumap, maxcpu)) { + vshError(ctl, "%s", _("No CPU specified")); + goto cleanup; + } + if (flags == -1) { if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0) goto cleanup; @@ -5755,10 +5774,11 @@ cmdEmulatorPin(vshControl *ctl, const vshCmd *cmd)
cpumaplen = VIR_CPU_MAPLEN(maxcpu);
- /* Query mode: show CPU affinity information then exit.*/ + /* Query mode: show CPU affinity information then exit. */ if (query) { /* When query mode and neither "live", "config" nor "current" - * is specified, set VIR_DOMAIN_AFFECT_CURRENT as flags */ + * is specified, set VIR_DOMAIN_AFFECT_CURRENT as flags. + */ if (flags == -1) flags = VIR_DOMAIN_AFFECT_CURRENT;
@@ -5775,10 +5795,15 @@ cmdEmulatorPin(vshControl *ctl, const vshCmd *cmd) goto cleanup; }
- /* Pin mode: pinning emulator threads to specified physical cpus*/ + /* Pin mode: pinning emulator threads to specified physical cpus. */ if (!(cpumap = vshParseCPUList(ctl, cpulist, maxcpu, cpumaplen))) goto cleanup;
+ if (vshIsCpumapAllClear(cpumap, maxcpu)) { + vshError(ctl, "%s", _("No CPU is specified")); + goto cleanup; + } + if (flags == -1) flags = VIR_DOMAIN_AFFECT_LIVE;
Unlike the virReportError() which provides the function trace - how would one know which of the two functions had the error here? OK other than looking at the code and noting one error has an "is" verb and the other doesn't...
Something like "vcpupin: No CPU is specified" should be clear enough to tell which function throws the error. But what I was thinking is the prefix "vcpupin:" is redundant. As one must known he is executing a "vcpupin" command. E.g. % virsh vcpupin toy 0 0,^0 error: No CPU specified
One message could indicate "No domain vCPU affinity" while the other could indicate "No domain emulator affinity"...
John
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

On 04/01/2013 11:42 PM, Osier Yang wrote:
This prohibits all clear cpumap eariler in virsh, for both vcpupin and emulatorpin.
Is that really necessary? Sometimes, letting virsh allow obviously wrong constructs, in order to prove that libvirt itself will flag things as sensible errors, makes for nicer testing. Virsh should only filter out obviously wrong things if it can give a nicer error message than what the underlying API would produce. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On 02/04/13 19:50, Eric Blake wrote:
On 04/01/2013 11:42 PM, Osier Yang wrote:
This prohibits all clear cpumap eariler in virsh, for both vcpupin and emulatorpin. Is that really necessary?
Honestly, I'm not sure. :-)
Sometimes, letting virsh allow obviously wrong constructs, in order to prove that libvirt itself will flag things as sensible errors, makes for nicer testing. Virsh should only filter out obviously wrong things if it can give a nicer error message than what the underlying API would produce.
I tended to error out earlier, but I also agreed with you that sometimes the good way is to let it fall through to driver. So I'm fine to drop this patch. Osier

--- src/libvirt_private.syms | 1 + src/util/virbitmap.c | 17 +++++++++++++++++ src/util/virbitmap.h | 3 +++ 3 files changed, 21 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index b7b9631..6b831b3 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1046,6 +1046,7 @@ virBitmapEqual; virBitmapFormat; virBitmapFree; virBitmapGetBit; +virBitmapIsAllClear; virBitmapIsAllSet; virBitmapNew; virBitmapNewCopy; diff --git a/src/util/virbitmap.c b/src/util/virbitmap.c index 21509ac..998c302 100644 --- a/src/util/virbitmap.c +++ b/src/util/virbitmap.c @@ -591,6 +591,23 @@ bool virBitmapIsAllSet(virBitmapPtr bitmap) } /** + * virBitmapIsAllClear: + * @bitmap: the bitmap to check + * + * check if all bits in @bitmap are clear + */ +bool virBitmapIsAllClear(virBitmapPtr bitmap) +{ + int i; + + for (i = 0; i < bitmap->map_len; i++) + if (bitmap->map[i] != 0) + return false; + + return true; +} + +/** * virBitmapNextSetBit: * @bitmap: the bitmap * @pos: the position after which to search for a set bit diff --git a/src/util/virbitmap.h b/src/util/virbitmap.h index 044c7a6..b682523 100644 --- a/src/util/virbitmap.h +++ b/src/util/virbitmap.h @@ -100,6 +100,9 @@ void virBitmapClearAll(virBitmapPtr bitmap) bool virBitmapIsAllSet(virBitmapPtr bitmap) ATTRIBUTE_NONNULL(1); +bool virBitmapIsAllClear(virBitmapPtr bitmap) + ATTRIBUTE_NONNULL(1); + ssize_t virBitmapNextSetBit(virBitmapPtr bitmap, ssize_t pos) ATTRIBUTE_NONNULL(1); -- 1.8.1.4

On 04/05/2013 10:32 AM, Osier Yang wrote:
--- src/libvirt_private.syms | 1 + src/util/virbitmap.c | 17 +++++++++++++++++ src/util/virbitmap.h | 3 +++ 3 files changed, 21 insertions(+)
The implementation looks correct, but I still think this patch should be the one that enhances the testsuite to prove that it works. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On 05/04/13 23:59, Eric Blake wrote:
--- src/libvirt_private.syms | 1 + src/util/virbitmap.c | 17 +++++++++++++++++ src/util/virbitmap.h | 3 +++ 3 files changed, 21 insertions(+) The implementation looks correct, but I still think this patch should be
On 04/05/2013 10:32 AM, Osier Yang wrote: the one that enhances the testsuite to prove that it works. Forgot it again, v3 posted. Thanks.
participants (4)
-
Daniel P. Berrange
-
Eric Blake
-
John Ferlan
-
Osier Yang