Re: [libvirt] [PATCH] rpc: Fix crash on error paths of message dispatching
Hi Eric, On Tue, Jan 29, 2013 at 02:21:30PM -0700, Eric Blake wrote: On 01/29/2013 01:22 PM, Guido Günther wrote: Hi, On Mon, Jan 28, 2013 at 07:35:38PM +0100, Peter Krempa wrote: When reading and dispatching of a message failed the message was freed but wasn't removed from the message queue. After that when the connection was about to be closed the pointer for the message was still present in the queue and it was passed to virNetMessageFree which tried to call the callback function from an uninitialized pointer. Debian stable is shipping 0.8.2. I checked and it seems this version isn't affected siince we properly remove the message from the queue before looking at it in daemon/libvirtd.c. I'd be great if somebody could double check though! 0.8.2 predates the RPC rewrite, and I concur with your assessment that back then, the code was _always_ clearing the queue: v0.8.2:daemon/libvirtd.c:qemudDispatchClientRead(): /* Grab the completed message */ struct qemud_client_message *msg = qemudClientMessageQueueServe(client-rx); struct qemud_client_filter *filter; /* Decode the header so we can use it for routing decisions */ if (remoteDecodeClientMessageHeader(msg) 0) { VIR_FREE(msg); qemudDispatchClientFailure(client); } However, it does look like there might be a missing 'return' statement after that error is reported, especially given that the next error reporting a few lines later does an early return. Thanks for double checking. It indeed looks like there's a return missing (cc:'ing the Debian bugreport to make this information permanent there too). Cheers, -- Guido But the best way to determine if this version is actually vulnerable to the CVE would be trying the exploit, and seeing if libvirtd survives with proper error logging about an invalid client request; Peter may have more details on how best to attempt that (although it may be better to discuss those details off-list, even if the CVE is already public, so that others are less likely to maliciously use the exploit). -- Eric Blake eblake redhat com+1-919-301-3266 Libvirt virtualization library http://libvirt.org -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] build: Add libcurl dependency to libvirt_driver.la
On Fri, Feb 01, 2013 at 01:45:19PM +0100, Jiri Denemark wrote: libvirt.c calls curl_global_init() if WITH_CURL is defined and thus it should be linked with libcurl. This fixes link failure in case neither xenapi nor esx driver is enabled (they are the only users of libcurl). In the case we link with libcurl just because user wants it. How about not exposing --with-curl but define WITH_CURL when needs to(xenapi or esx driver is enabled, or both)? -- Regards, Hu Tao -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] How to connect to console of domain on PowerPC?
Hi, I tried to use libvirt to run KVM/QEMU on Freescale PowerPC platforms. So far there's only one serial device (spapr-vty) defined in QEMU to work as console for IBM PSeries platform. There's no serial device support in QEMU for Freescale PowerPC (ePAPR). libvirt/src/qemu/qemu_command.c /* This function generates the correct '-device' string for character * devices of each architecture. */ char * qemuBuildChrDeviceStr(virDomainChrDefPtr serial, virBitmapPtr qemuCaps, char *os_arch, char *machine) { virBuffer cmd = VIR_BUFFER_INITIALIZER; if (STREQ(os_arch, ppc64) STREQ(machine, pseries)) { if (serial-deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL serial-source.type == VIR_DOMAIN_CHR_TYPE_PTY serial-info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO) { virBufferAsprintf(cmd, spapr-vty,chardev=char%s, serial-info.alias); if (qemuBuildDeviceAddressStr(cmd, serial-info, qemuCaps) 0) goto error; } } else virBufferAsprintf(cmd, isa-serial,chardev=char%s,id=%s, serial-info.alias, serial-info.alias); if (virBufferError(cmd)) { virReportOOMError(); goto error; } return virBufferContentAndReset(cmd); error: virBufferFreeAndReset(cmd); return NULL; } We usually connect guest with telnet. For instance, /usr/bin/qemu-system-ppc -name demo -M ppce500v2 -enable-kvm -m 256 -nographic -kernel /media/ram/uImage -initrd /media/ram/ramdisk -append root=/dev/ram rw console=ttyS0,115200 -serial tcp::4445,server Then to run 'telnet 10.193.20.xxx 4445' could connect the guest. The temporary workaround is not add '-device' string after '-serial' option. diff -Nur libvirt-0.10.1.orig/src/qemu/qemu_command.c libvirt-0.10.1/src/qemu/qemu_command.c --- libvirt-0.10.1.orig/src/qemu/qemu_command.c 2012-08-30 15:35:18.0 +0530 +++ libvirt-0.10.1/src/qemu/qemu_command.c 2012-10-05 17:19:32.060368755 +0530 @@ -5501,13 +5501,15 @@ virCommandAddArg(cmd, devstr); VIR_FREE(devstr); -virCommandAddArg(cmd, -device); -if (!(devstr = qemuBuildChrDeviceStr(serial, qemuCaps, +if (!STREQ(def-os.arch, ppc)) { +virCommandAddArg(cmd, -device); +if (!(devstr = qemuBuildChrDeviceStr(serial, + qemuCaps, def-os.arch, def-os.machine))) - goto error; -virCommandAddArg(cmd, devstr); -VIR_FREE(devstr); +goto error; +virCommandAddArg(cmd, devstr); +VIR_FREE(devstr); +} } else { virCommandAddArg(cmd, -serial); if (!(devstr = qemuBuildChrArgStr(serial-source, NULL))) Applying the above patch to libvirt, all the other domain control commands could work except 'virsh console domain'. # cat demo.args EOF /usr/bin/qemu-system-ppc -name demo -M ppce500v2 -enable-kvm -m 256 -nographic -kernel /media/ram/uImage -initrd /media/ram/ramdisk -append root=/dev/ram rw console=ttyS0,115200 -serial tcp::4445,server -net nic EOF # vi demo.args /usr/bin/qemu-system-ppc -name demo -M ppce500v2 -enable-kvm -m 256 -nographic -kernel /media/ram/uImage -initrd /media/ram/ramdisk -append root=/dev/ram rw console=ttyS0,115200 -serial tcp::4445,server -net nic # virsh domxml-from-native qemu-argv demo.args demo.xml # vi demo.xml domain type='kvm' namedemo/name uuid985d7154-83c8-0763-cbac-ecd159eee8a6/uuid memory unit='KiB'262144/memory currentMemory unit='KiB'262144/currentMemory vcpu placement='static'1/vcpu os type arch='ppc' machine='ppce500v2'hvm/type kernel/media/ram/uImage/kernel initrd/media/ram/ramdisk/initrd cmdlineroot=/dev/ram rw console=ttyS0,115200/cmdline /os clock offset='utc'/ on_poweroffdestroy/on_poweroff on_rebootrestart/on_reboot on_crashdestroy/on_crash devices emulator/usr/bin/qemu-system-ppc/emulator serial type='tcp' source mode='bind' host='' service='4445'/ protocol type='raw'/ target port='0'/ /serial console type='tcp' source mode='bind' host='' service='4445'/ protocol type='raw'/ target type='serial' port='0'/ /console memballoon model='virtio'/ /devices /domain # virsh -c qemu:///system define demo.xml # virsh -c qemu:///system start demo But it seemed that can't connect to the console. # virsh -c qemu:///system console demo Connected to domain test Escape character is ^] error: internal error character device (null) is not using a PTY I tried also use '-serial pty' option, /usr/bin/qemu-system-ppc -name test -M ppce500v2 -enable-kvm -m 256
[libvirt] A question about booting from the snapshot image by specifying snapshot id in Libvirt
Hi all, I test libvirt boots QEMU VM from Sheepdog snapshot image by specify snapshot id like following. 1, $ collie vdi list NameIdSizeUsed SharedCreation time VDI id Copies Tag Alice1 10 GB 1.3 GB 0.0 MB 2013-02-01 18:59 15d167 2 s testvdi 1 20 MB 20 MB 0.0 MB 2013-02-02 11:45 f348ba 2 name s testvdi 2 20 MB 0.0 MB 20 MB 2013-02-03 17:56 f348bb 2 testvdi 3 20 MB 12 MB 8.0 MB 2013-02-03 17:58 f348bc 2 2, $ cat sheepdog_vm1.xml domain type='qemu' nametestvm/name memory1048576/memory os type arch='x86_64'hvm/type /os devices disk type='network' source protocol=sheepdog name=testvdi:1/ target dev='hda' bus='ide'/ /disk graphics type='vnc' port='-1' autoport='yes'/ /devices /domain 3, $ virsh create sheepdog_vm1.xml domain testvm is created ( from sheepdog_vm1.xml) 4, $ virsh destroy testvm domain testvm is deleted 5, $ collie vdi list NameIdSizeUsed SharedCreation time VDI id Copies Tag Alice1 10 GB 1.3 GB 0.0 MB 2013-02-01 18:59 15d167 2 s testvdi 1 20 MB 20 MB 0.0 MB 2013-02-02 11:45 f348ba 2 name s testvdi 2 20 MB 0.0 MB 20 MB 2013-02-03 17:56 f348bb 2 s testvdi 3 20 MB 12 MB 8.0 MB 2013-02-03 17:58 f348bc 2 testvdi 4 20 MB 12 MB 8.0 MB 2013-02-04 13:15 f348bd 2 My question is before i boot VM from sheepdog:testvdi:1, my vdi list like NameIdSizeUsed SharedCreation time VDI id Copies Tag Alice1 10 GB 1.3 GB 0.0 MB 2013-02-01 18:59 15d167 2 s testvdi 1 20 MB 20 MB 0.0 MB 2013-02-02 11:45 f348ba 2 name s testvdi 2 20 MB 0.0 MB 20 MB 2013-02-03 17:56 f348bb 2 testvdi 3 20 MB 12 MB 8.0 MB 2013-02-03 17:58 f348bc 2 However, after VM is destroied, my vdi list like NameIdSizeUsed SharedCreation time VDI id Copies Tag Alice1 10 GB 1.3 GB 0.0 MB 2013-02-01 18:59 15d167 2 s testvdi 1 20 MB 20 MB 0.0 MB 2013-02-02 11:45 f348ba 2 name s testvdi 2 20 MB 0.0 MB 20 MB 2013-02-03 17:56 f348bb 2 s testvdi 3 20 MB 12 MB 8.0 MB 2013-02-03 17:58 f348bc 2 testvdi 4 20 MB 12 MB 8.0 MB 2013-02-04 13:15 f348bd 2 There is another snapshot of testvdi created. I am not clear about why another one is created? I just boot a VM from snapshot testvdi, which id is 1. Could anyone please give me some suggestions? Thanks in advance ;-) -- Thanks Harry Wei -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 0/5] cgroup refactor
This series refactors cgroup code to: - provide lazy creation of cgroup directories, despite of what level they are. - remove cgroup directories if no one is using the corresponding virCgroup. This series is splitted in a manner for easier review. Patch 2 is the main implementation. Patch 3, 4, 5 should have been squashed into one in order to build, but harder to review. Hu Tao (5): refactor virCgroupDetectMounts and virCgroupDetectPlacement cgroup: refactor virCgroup cgroup: replace old cgroup qemu: replace old cgroup lxc: replace old cgroup src/conf/domain_conf.h|5 + src/libvirt_private.syms |7 +- src/lxc/lxc_cgroup.c | 40 +- src/lxc/lxc_cgroup.h |2 +- src/lxc/lxc_controller.c | 31 +- src/lxc/lxc_driver.c | 177 +++ src/lxc/lxc_process.c | 19 +- src/qemu/qemu_cgroup.c| 162 +++--- src/qemu/qemu_cgroup.h|3 +- src/qemu/qemu_driver.c| 351 + src/qemu/qemu_hotplug.c | 21 +- src/qemu/qemu_migration.c | 20 +- src/qemu/qemu_process.c |7 +- src/util/vircgroup.c | 1263 + src/util/vircgroup.h | 19 +- 15 files changed, 921 insertions(+), 1206 deletions(-) -- 1.8.0.1.240.ge8a1f5a -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 5/5] lxc: replace old cgroup
--- src/lxc/lxc_cgroup.c | 40 +++ src/lxc/lxc_cgroup.h | 2 +- src/lxc/lxc_controller.c | 31 - src/lxc/lxc_driver.c | 177 +-- src/lxc/lxc_process.c| 19 +++-- 5 files changed, 111 insertions(+), 158 deletions(-) diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c index 1984c5f..d1a1f16 100644 --- a/src/lxc/lxc_cgroup.c +++ b/src/lxc/lxc_cgroup.c @@ -242,7 +242,7 @@ int virLXCCgroupGetMeminfo(virLXCMeminfoPtr meminfo) int ret; virCgroupPtr cgroup; -ret = virCgroupGetAppRoot(cgroup); +ret = virCgroupGetAppRoot(cgroup, true); if (ret 0) { virReportSystemError(-ret, %s, _(Unable to get cgroup for container)); @@ -469,53 +469,29 @@ cleanup: } -int virLXCCgroupSetup(virDomainDefPtr def) +int virLXCCgroupSetup(virCgroupPtr cgroup, virDomainDefPtr def) { -virCgroupPtr driver = NULL; -virCgroupPtr cgroup = NULL; -int ret = -1; int rc; -rc = virCgroupForDriver(lxc, driver, 1, 0); -if (rc != 0) { -virReportSystemError(-rc, %s, - _(Unable to get cgroup for driver)); -goto cleanup; -} - -rc = virCgroupForDomain(driver, def-name, cgroup, 1); -if (rc != 0) { -virReportSystemError(-rc, - _(Unable to create cgroup for domain %s), - def-name); -goto cleanup; -} - if (virLXCCgroupSetupCpuTune(def, cgroup) 0) -goto cleanup; +return -1; if (virLXCCgroupSetupBlkioTune(def, cgroup) 0) -goto cleanup; +return -1; if (virLXCCgroupSetupMemTune(def, cgroup) 0) -goto cleanup; +return -1; if (virLXCCgroupSetupDeviceACL(def, cgroup) 0) -goto cleanup; +return -1; rc = virCgroupAddTask(cgroup, getpid()); if (rc != 0) { virReportSystemError(-rc, _(Unable to add task %d to cgroup for domain %s), getpid(), def-name); -goto cleanup; +return -1; } -ret = 0; - -cleanup: -virCgroupFree(cgroup); -virCgroupFree(driver); - -return ret; +return 0; } diff --git a/src/lxc/lxc_cgroup.h b/src/lxc/lxc_cgroup.h index 97b94e5..cd02b46 100644 --- a/src/lxc/lxc_cgroup.h +++ b/src/lxc/lxc_cgroup.h @@ -26,7 +26,7 @@ # include lxc_fuse.h # include virusb.h -int virLXCCgroupSetup(virDomainDefPtr def); +int virLXCCgroupSetup(virCgroupPtr cgroup, virDomainDefPtr def); int virLXCCgroupGetMeminfo(virLXCMeminfoPtr meminfo); int diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 2673f72..4a7a63b 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -130,6 +130,8 @@ struct _virLXCController { int timerShutdown; virLXCFusePtr fuse; + +virCgroupPtr cgroup; }; #include lxc_controller_dispatch.h @@ -272,6 +274,8 @@ static void virLXCControllerFree(virLXCControllerPtr ctrl) VIR_FREE(ctrl-devptmx); +virCgroupFree(ctrl-cgroup); + virDomainDefFree(ctrl-def); VIR_FREE(ctrl-name); @@ -548,6 +552,31 @@ static int virLXCControllerSetupCpuAffinity(virLXCControllerPtr ctrl) return 0; } +static int virLXCControllerSetupCgroup(virLXCControllerPtr ctrl) +{ +virCgroupPtr appCgroup = NULL; +int rc; + +rc = virCgroupGetAppRoot(appCgroup, true); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(Unable to get cgroup for libvirt)); +goto cleanup; +} + +rc = virCgroupNew(lxc, appCgroup, ctrl-cgroup); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(Unable to get cgroup for driver)); +goto cleanup; +} + +rc = virLXCCgroupSetup(ctrl-cgroup, ctrl-def); + +cleanup: +virCgroupFree(appCgroup); +return rc; +} /** * virLXCControllerSetupResourceLimits @@ -567,7 +596,7 @@ static int virLXCControllerSetupResourceLimits(virLXCControllerPtr ctrl) if (virLXCControllerSetupNUMAPolicy(ctrl) 0) return -1; -return virLXCCgroupSetup(ctrl-def); +return virLXCControllerSetupCgroup(ctrl); } diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 1fe8039..7afe969 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -527,7 +527,6 @@ static int lxcDomainGetInfo(virDomainPtr dom, { virLXCDriverPtr driver = dom-conn-privateData; virDomainObjPtr vm; -virCgroupPtr cgroup = NULL; int ret = -1, rc; lxcDriverLock(driver); @@ -543,22 +542,16 @@ static int lxcDomainGetInfo(virDomainPtr dom, info-state = virDomainObjGetState(vm, NULL); -if (!virDomainObjIsActive(vm) || driver-cgroup == NULL) { +if (!virDomainObjIsActive(vm) || vm-cgroup == NULL) { info-cpuTime = 0; info-memory = vm-def-mem.cur_balloon; } else { -if
[libvirt] [PATCH v2 3/5] cgroup: replace old cgroup
--- src/libvirt_private.syms | 9 +- src/util/vircgroup.c | 812 +++ src/util/vircgroup.h | 25 +- 3 files changed, 112 insertions(+), 734 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index f5138af..78e387d 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -73,8 +73,6 @@ virCapabilitiesSetMacPrefix; # cgroup.h -virCgroup2Free; -virCgroup2New; virCgroupAddTask; virCgroupAddTaskController; virCgroupAllowDevice; @@ -86,10 +84,6 @@ virCgroupDenyAllDevices; virCgroupDenyDevice; virCgroupDenyDeviceMajor; virCgroupDenyDevicePath; -virCgroupForDomain; -virCgroupForDriver; -virCgroupForEmulator; -virCgroupForVcpu; virCgroupFree; virCgroupGetAppRoot; virCgroupGetBlkioWeight; @@ -110,10 +104,11 @@ virCgroupGetMemSwapUsage; virCgroupKill; virCgroupKillPainfully; virCgroupKillRecursive; +virCgroupMakePath; virCgroupMounted; virCgroupMoveTask; +virCgroupNew; virCgroupPathOfController; -virCgroupRemove; virCgroupSetBlkioDeviceWeight; virCgroupSetBlkioWeight; virCgroupSetCpuCfsPeriod; diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c index dbc9688..90ff97c 100644 --- a/src/util/vircgroup.c +++ b/src/util/vircgroup.c @@ -80,7 +80,7 @@ struct _virCgroupItem { struct virCgroupController controllers[VIR_CGROUP_CONTROLLER_LAST]; }; -struct virCgroup2 { +struct virCgroup { virCgroupItemPtr items[VIR_CGROUP_CONTROLLER_LAST]; }; @@ -145,12 +145,6 @@ static int virCgroupControllersInit(struct virCgroupController (*controllers)[VI return rc; } -struct virCgroup { -char *path; - -struct virCgroupController controllers[VIR_CGROUP_CONTROLLER_LAST]; -}; - typedef enum { VIR_CGROUP_NONE = 0, /* create subdir under each cgroup if possible. */ VIR_CGROUP_MEM_HIERACHY = 1 0, /* call virCgroupSetMemoryUseHierarchy @@ -447,9 +441,21 @@ static int virCgroupItemKeyPath(virCgroupItemPtr cgroupItem, return ret; } -int virCgroup2New(const char *name, virCgroup2Ptr parent, virCgroup2Ptr *cgroup) +int virCgroupMakePath(virCgroupPtr cgroup) { -virCgroup2Ptr newCgroup = NULL; +int i; + +for (i = 0; i VIR_CGROUP_CONTROLLER_LAST; i++) { +if (virCgroupItemPath(cgroup-items[i], true, NULL) != 0) +return -1; +} + +return 0; +} + +int virCgroupNew(const char *name, virCgroupPtr parent, virCgroupPtr *cgroup) +{ +virCgroupPtr newCgroup = NULL; virCgroupItemPtr *parentCgroupItems; int ret = -1; int i = 0; @@ -502,40 +508,24 @@ error: return ret; } -void virCgroup2Free(virCgroup2Ptr *cgroup) -{ -int i; - -if (!cgroup || !*cgroup) -return; - -for (i = 0; i VIR_CGROUP_CONTROLLER_LAST; i++) { -virCgroupItemFree((*cgroup)-items[i]); -} - -VIR_FREE(*cgroup); -*cgroup = NULL; -} - /** * virCgroupFree: * * @group: The group structure to free */ -void virCgroupFree(virCgroupPtr *group) +void virCgroupFree(virCgroupPtr *cgroup) { int i; -if (*group == NULL) +if (!cgroup || !*cgroup) return; -for (i = 0 ; i VIR_CGROUP_CONTROLLER_LAST ; i++) { -VIR_FREE((*group)-controllers[i].mountPoint); -VIR_FREE((*group)-controllers[i].placement); +for (i = 0; i VIR_CGROUP_CONTROLLER_LAST; i++) { +virCgroupItemFree((*cgroup)-items[i]); } -VIR_FREE((*group)-path); -VIR_FREE(*group); +VIR_FREE(*cgroup); +*cgroup = NULL; } /** @@ -546,9 +536,13 @@ void virCgroupFree(virCgroupPtr *group) * * Returns true if a cgroup is subsystem is mounted. */ -bool virCgroupMounted(virCgroupPtr cgroup, int controller) +bool virCgroupMounted(virCgroupPtr cgroup ATTRIBUTE_UNUSED, + int controller) { -return cgroup-controllers[controller].mountPoint != NULL; +if (rootCgroupItems[controller] +rootCgroupItems[controller]-controllers[controller].mountPoint) +return true; +return false; } #if defined HAVE_MNTENT_H defined HAVE_GETMNTENT_R @@ -675,58 +669,8 @@ no_memory: } - -static int virCgroupDetect(virCgroupPtr group) -{ -int any = 0; -int rc; -int i; - -rc = virCgroupDetectMounts(group-controllers); -if (rc 0) { -VIR_ERROR(_(Failed to detect mounts for %s), group-path); -return rc; -} - -/* Check that at least 1 controller is available */ -for (i = 0 ; i VIR_CGROUP_CONTROLLER_LAST ; i++) { -if (group-controllers[i].mountPoint != NULL) -any = 1; -} -if (!any) -return -ENXIO; - - -rc = virCgroupDetectPlacement(group-controllers); - -if (rc == 0) { -/* Check that for every mounted controller, we found our placement */ -for (i = 0 ; i VIR_CGROUP_CONTROLLER_LAST ; i++) { -if (!group-controllers[i].mountPoint) -continue; - -if (!group-controllers[i].placement) { -VIR_ERROR(_(Could not
[libvirt] [PATCH v2 1/5] refactor virCgroupDetectMounts and virCgroupDetectPlacement
This patch prepares for the next one. --- src/util/vircgroup.c | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c index 48cba93..71d46c5 100644 --- a/src/util/vircgroup.c +++ b/src/util/vircgroup.c @@ -113,7 +113,7 @@ bool virCgroupMounted(virCgroupPtr cgroup, int controller) * Process /proc/mounts figuring out what controllers are * mounted and where */ -static int virCgroupDetectMounts(virCgroupPtr group) +static int virCgroupDetectMounts(struct virCgroupController (*controllers)[VIR_CGROUP_CONTROLLER_LAST]) { int i; FILE *mounts = NULL; @@ -148,8 +148,8 @@ static int virCgroupDetectMounts(virCgroupPtr group) * first entry only */ if (typelen == len STREQLEN(typestr, tmp, len) -!group-controllers[i].mountPoint -!(group-controllers[i].mountPoint = strdup(entry.mnt_dir))) +!(*controllers)[i].mountPoint +!((*controllers)[i].mountPoint = strdup(entry.mnt_dir))) goto no_memory; tmp = next; } @@ -171,7 +171,7 @@ no_memory: * sub-path the current process is assigned to. ie not * necessarily in the root */ -static int virCgroupDetectPlacement(virCgroupPtr group) +static int virCgroupDetectPlacement(struct virCgroupController (*cgroupControllers)[VIR_CGROUP_CONTROLLER_LAST]) { int i; FILE *mapping = NULL; @@ -212,7 +212,7 @@ static int virCgroupDetectPlacement(virCgroupPtr group) len = strlen(tmp); } if (typelen == len STREQLEN(typestr, tmp, len) -!(group-controllers[i].placement = strdup(STREQ(path, /) ? : path))) +!((*cgroupControllers)[i].placement = strdup(STREQ(path, /) ? : path))) goto no_memory; tmp = next; @@ -236,7 +236,7 @@ static int virCgroupDetect(virCgroupPtr group) int rc; int i; -rc = virCgroupDetectMounts(group); +rc = virCgroupDetectMounts(group-controllers); if (rc 0) { VIR_ERROR(_(Failed to detect mounts for %s), group-path); return rc; @@ -251,7 +251,7 @@ static int virCgroupDetect(virCgroupPtr group) return -ENXIO; -rc = virCgroupDetectPlacement(group); +rc = virCgroupDetectPlacement(group-controllers); if (rc == 0) { /* Check that for every mounted controller, we found our placement */ -- 1.8.0.1.240.ge8a1f5a -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 2/5] cgroup: refactor virCgroup
This patch adds a new structure, virCgroupItem, to represent a cgroup directory(named cgroup item). cgroup directory is created when needed and removed if no one is using it. --- src/libvirt_private.syms | 2 + src/util/vircgroup.c | 541 ++- src/util/vircgroup.h | 8 + 3 files changed, 545 insertions(+), 6 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index c589236..f5138af 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -73,6 +73,8 @@ virCapabilitiesSetMacPrefix; # cgroup.h +virCgroup2Free; +virCgroup2New; virCgroupAddTask; virCgroupAddTaskController; virCgroupAllowDevice; diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c index 71d46c5..dbc9688 100644 --- a/src/util/vircgroup.c +++ b/src/util/vircgroup.c @@ -37,6 +37,7 @@ #include libgen.h #include dirent.h +#include virobject.h #include internal.h #include virutil.h #include viralloc.h @@ -45,6 +46,7 @@ #include virfile.h #include virhash.h #include virhashcode.h +#include virthread.h #define CGROUP_MAX_VAL 512 @@ -58,6 +60,91 @@ struct virCgroupController { char *placement; }; +struct _virCgroupItem; +typedef struct _virCgroupItem virCgroupItem; +typedef virCgroupItem *virCgroupItemPtr; + +struct _virCgroupItem { +virObjectLockable object; + +char *name; +char *path; + +bool created; /* the path is created or not */ + +virCgroupItemPtr next; +virCgroupItemPtr parent; +virCgroupItemPtr children; + +int type; +struct virCgroupController controllers[VIR_CGROUP_CONTROLLER_LAST]; +}; + +struct virCgroup2 { +virCgroupItemPtr items[VIR_CGROUP_CONTROLLER_LAST]; +}; + +static virClassPtr cgroupItemClass; + +static void cgroupItemDispose(void *obj); + +static int virCgroupItemOnceInit(void) +{ +if (!(cgroupItemClass = virClassNew(virClassForObjectLockable(), +cgroupItem, +sizeof(virCgroupItem), +cgroupItemDispose))) +return -1; + +return 0; +} +VIR_ONCE_GLOBAL_INIT(virCgroupItem); + +static virCgroupItemPtr rootCgroupItems[VIR_CGROUP_CONTROLLER_LAST]; + +static virCgroupItemPtr virCgroupItemRootNew(int type); +static int virCgroupDetectMounts(struct virCgroupController (*controllers)[VIR_CGROUP_CONTROLLER_LAST]); +static int virCgroupDetectPlacement(struct virCgroupController (*controllers)[VIR_CGROUP_CONTROLLER_LAST]); + +static int virCgroupControllersInit(struct virCgroupController (*controllers)[VIR_CGROUP_CONTROLLER_LAST]) +{ +int rc; +int i; + +rc = virCgroupDetectMounts(controllers); +if (rc 0) { +VIR_ERROR(_(Failed to initialize cgroup controllers)); +return rc; +} + +rc = virCgroupDetectPlacement(controllers); + +if (rc == 0) { +/* Check that for every mounted controller, we found our placement */ +for (i = 0 ; i VIR_CGROUP_CONTROLLER_LAST ; i++) { +if (!(*controllers)[i].mountPoint) +continue; + +if (!(*controllers)[i].placement) { +VIR_ERROR(_(Could not find placement for controller %s at %s), + virCgroupControllerTypeToString(i), + (*controllers)[i].placement); +rc = -ENOENT; +break; +} + +VIR_DEBUG(Detected mount/mapping %i:%s at %s in %s, i, + virCgroupControllerTypeToString(i), + (*controllers)[i].mountPoint, + (*controllers)[i].placement); +} +} else { +VIR_ERROR(_(Failed to initialize cgroup controllers)); +} + +return rc; +} + struct virCgroup { char *path; @@ -74,6 +161,362 @@ typedef enum { * cpuacct and cpuset if possible. */ } virCgroupFlags; +static virCgroupItemPtr virCgroupItemRootNew(int type) +{ +virCgroupItemPtr rootItem = NULL; + +if (type = VIR_CGROUP_CONTROLLER_LAST || type 0) +return NULL; + +if (virCgroupItemInitialize() 0) +return NULL; + +if (!(rootItem = virObjectNew(cgroupItemClass))) +return NULL; + +if (virCgroupControllersInit(rootItem-controllers) != 0) { +virObjectUnref(rootItem); +rootItem = NULL; +return NULL; +} + +rootItem-name = strdup(/); +rootItem-next = NULL; +rootItem-parent = NULL; +rootItem-children = NULL; +rootItem-created = 1; +rootItem-type = type; +if (virAsprintf(rootItem-path, %s%s, +rootItem-controllers[rootItem-type].mountPoint, +rootItem-controllers[rootItem-type].placement) 0) { +virObjectUnref(rootItem); +rootItem = NULL; +} + +return rootItem; +} + +static virCgroupItemPtr virCgroupHasChildByName(virCgroupItemPtr item, +