From 361ff0a0881757efeb53d97659006899346948ba Mon Sep 17 00:00:00 2001 From: Michal Privoznik Date: Wed, 16 Aug 2017 12:55:03 +0200 Subject: [PATCH] network: Use self inflating bitmap for class IDs Back in the day when I was implementing QoS for networks there were no self inflating virBitmaps. Only the static ones. Therefore, I had to allocate the whole 8KB of memory in order to keep track of used/unused class IDs. This is rather wasteful because nobody is ever gonna use that much classes (kernel overhead would drastically lower the bandwidth). Anyway, now that we have self inflating bitmaps we can start small and allocate more if there's need for it. Signed-off-by: Michal Privoznik Reviewed-by: John Ferlan --- src/conf/virnetworkobj.c | 18 ++++++++++-------- src/network/bridge_driver.c | 5 +++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/conf/virnetworkobj.c b/src/conf/virnetworkobj.c index b16844d54f..2bd69dcf5b 100644 --- a/src/conf/virnetworkobj.c +++ b/src/conf/virnetworkobj.c @@ -34,8 +34,10 @@ VIR_LOG_INIT("conf.virnetworkobj"); -/* currently, /sbin/tc implementation allows up to 16 bits for minor class size */ -#define CLASS_ID_BITMAP_SIZE (1<<16) +/* Currently, /sbin/tc implementation allows up to 16 bits for + * minor class size. But the initial bitmap doesn't have to be + * that big. */ +#define INIT_CLASS_ID_BITMAP_SIZE (1<<4) struct _virNetworkObj { virObjectLockable parent; @@ -100,13 +102,14 @@ virNetworkObjNew(void) if (!(obj = virObjectLockableNew(virNetworkObjClass))) return NULL; - if (!(obj->classIdMap = virBitmapNew(CLASS_ID_BITMAP_SIZE))) + if (!(obj->classIdMap = virBitmapNew(INIT_CLASS_ID_BITMAP_SIZE))) goto error; /* The first three class IDs are already taken */ - ignore_value(virBitmapSetBit(obj->classIdMap, 0)); - ignore_value(virBitmapSetBit(obj->classIdMap, 1)); - ignore_value(virBitmapSetBit(obj->classIdMap, 2)); + if (virBitmapSetBitExpand(obj->classIdMap, 0) < 0 || + virBitmapSetBitExpand(obj->classIdMap, 1) < 0 || + virBitmapSetBitExpand(obj->classIdMap, 2) < 0) + goto error; virObjectLock(obj); @@ -909,8 +912,7 @@ virNetworkLoadState(virNetworkObjListPtr nets, ctxt->node = node; if ((classIdStr = virXPathString("string(./class_id[1]/@bitmap)", ctxt))) { - if (virBitmapParse(classIdStr, &classIdMap, - CLASS_ID_BITMAP_SIZE) < 0) { + if (!(classIdMap = virBitmapParseUnlimited(classIdStr))) { VIR_FREE(classIdStr); goto error; } diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 74ce92e434..e8d093a314 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -5395,9 +5395,10 @@ networkNextClassID(virNetworkObjPtr obj) ssize_t ret = 0; virBitmapPtr classIdMap = virNetworkObjGetClassIdMap(obj); - ret = virBitmapNextClearBit(classIdMap, -1); + if ((ret = virBitmapNextClearBit(classIdMap, -1)) < 0) + ret = virBitmapSize(classIdMap); - if (ret < 0 || virBitmapSetBit(classIdMap, ret) < 0) + if (virBitmapSetBitExpand(classIdMap, ret) < 0) return -1; return ret;