Merge lp:~serge-hallyn/ubuntu/raring/libvirt/libvirt-hugepages into lp:ubuntu/raring/libvirt

Proposed by Serge Hallyn
Status: Needs review
Proposed branch: lp:~serge-hallyn/ubuntu/raring/libvirt/libvirt-hugepages
Merge into: lp:ubuntu/raring/libvirt
Diff against target: 11034 lines (+10828/-0)
24 files modified
.pc/apparmor-allow-hugepages/src/libvirt_private.syms (+1840/-0)
.pc/apparmor-allow-hugepages/src/qemu/qemu_process.c (+4474/-0)
.pc/apparmor-allow-hugepages/src/security/security_apparmor.c (+911/-0)
.pc/apparmor-allow-hugepages/src/security/security_driver.h (+148/-0)
.pc/apparmor-allow-hugepages/src/security/security_manager.c (+513/-0)
.pc/apparmor-allow-hugepages/src/security/security_manager.h (+116/-0)
.pc/apparmor-allow-hugepages/src/security/security_stack.c (+532/-0)
.pc/apparmor-allow-hugepages/tests/virt-aa-helper-test (+326/-0)
.pc/applied-patches (+2/-0)
.pc/vnc-socket.patch/src/security/virt-aa-helper.c (+1314/-0)
.pc/vnc-socket.patch/tests/virt-aa-helper-test (+329/-0)
debian/changelog (+9/-0)
debian/patches/apparmor-allow-hugepages (+189/-0)
debian/patches/series (+2/-0)
debian/patches/vnc-socket.patch (+37/-0)
src/libvirt_private.syms (+1/-0)
src/qemu/qemu_process.c (+9/-0)
src/security/security_apparmor.c (+27/-0)
src/security/security_driver.h (+4/-0)
src/security/security_manager.c (+10/-0)
src/security/security_manager.h (+3/-0)
src/security/security_stack.c (+19/-0)
src/security/virt-aa-helper.c (+7/-0)
tests/virt-aa-helper-test (+6/-0)
To merge this branch: bzr merge lp:~serge-hallyn/ubuntu/raring/libvirt/libvirt-hugepages
Reviewer Review Type Date Requested Status
Jamie Strandboge Pending
Review via email: mp+138341@code.launchpad.net

Description of the change

This has proposed changes for vnc socket files and hugepages backing stores. Both have been tested and appear to work, but given my un-familiarity with the relevant code before I started, I'd appreciate a review to make sure I didn't mis-interpret any of the code.

To post a comment you must log in.
228. By Serge Hallyn

Switch to using virBuffer

229. By Serge Hallyn

add tests for vnc and hugepages apparmor extensions

230. By Serge Hallyn

fix bad cut-pastes

Unmerged revisions

230. By Serge Hallyn

fix bad cut-pastes

229. By Serge Hallyn

add tests for vnc and hugepages apparmor extensions

228. By Serge Hallyn

Switch to using virBuffer

227. By Serge Hallyn

debian/patches/vnc-socket.patch: If a vnc socket is in use, add it's
path to the apparmor policy. (LP: #1069534)

Note - I'm not sure whether there are non-unix-socket cases which are
mis-handled by this.

226. By Serge Hallyn

debian/patches/apparmor-allow-hugepages: update apparmor policies to
allow use of hugepages. (LP: #646468)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory '.pc/apparmor-allow-hugepages'
2=== added file '.pc/apparmor-allow-hugepages/.timestamp'
3=== added directory '.pc/apparmor-allow-hugepages/src'
4=== added file '.pc/apparmor-allow-hugepages/src/libvirt_private.syms'
5--- .pc/apparmor-allow-hugepages/src/libvirt_private.syms 1970-01-01 00:00:00 +0000
6+++ .pc/apparmor-allow-hugepages/src/libvirt_private.syms 2012-12-11 20:02:29 +0000
7@@ -0,0 +1,1840 @@
8+#
9+# General private symbols. Add symbols here, and see Makefile.am for
10+# more details.
11+#
12+# Keep this file sorted by header name, then by symbols with each header.
13+#
14+
15+# bitmap.h
16+virBitmapClearAll;
17+virBitmapClearBit;
18+virBitmapCopy;
19+virBitmapCountBits;
20+virBitmapEqual;
21+virBitmapFormat;
22+virBitmapFree;
23+virBitmapGetBit;
24+virBitmapIsAllSet;
25+virBitmapNew;
26+virBitmapNewCopy;
27+virBitmapNewData;
28+virBitmapNextSetBit;
29+virBitmapParse;
30+virBitmapSetAll;
31+virBitmapSetBit;
32+virBitmapSize;
33+virBitmapString;
34+virBitmapToData;
35+
36+
37+# buf.h
38+virBufferAdd;
39+virBufferAddChar;
40+virBufferAdjustIndent;
41+virBufferAsprintf;
42+virBufferContentAndReset;
43+virBufferCurrentContent;
44+virBufferError;
45+virBufferEscape;
46+virBufferEscapeSexpr;
47+virBufferEscapeShell;
48+virBufferEscapeString;
49+virBufferFreeAndReset;
50+virBufferGetIndent;
51+virBufferStrcat;
52+virBufferTrim;
53+virBufferURIEncodeString;
54+virBufferUse;
55+virBufferVasprintf;
56+
57+
58+# caps.h
59+virCapabilitiesAddGuest;
60+virCapabilitiesAddGuestDomain;
61+virCapabilitiesAddGuestFeature;
62+virCapabilitiesAddHostFeature;
63+virCapabilitiesAddHostMigrateTransport;
64+virCapabilitiesAddHostNUMACell;
65+virCapabilitiesAllocMachines;
66+virCapabilitiesDefaultGuestArch;
67+virCapabilitiesDefaultGuestEmulator;
68+virCapabilitiesDefaultGuestMachine;
69+virCapabilitiesFormatXML;
70+virCapabilitiesFree;
71+virCapabilitiesFreeMachines;
72+virCapabilitiesFreeNUMAInfo;
73+virCapabilitiesGenerateMac;
74+virCapabilitiesIsEmulatorRequired;
75+virCapabilitiesNew;
76+virCapabilitiesSetEmulatorRequired;
77+virCapabilitiesSetHostCPU;
78+virCapabilitiesSetMacPrefix;
79+
80+
81+# cgroup.h
82+virCgroupAddTask;
83+virCgroupAddTaskController;
84+virCgroupAllowDevice;
85+virCgroupAllowDeviceMajor;
86+virCgroupAllowDevicePath;
87+virCgroupControllerTypeFromString;
88+virCgroupControllerTypeToString;
89+virCgroupDenyAllDevices;
90+virCgroupDenyDevice;
91+virCgroupDenyDeviceMajor;
92+virCgroupDenyDevicePath;
93+virCgroupForDomain;
94+virCgroupForDriver;
95+virCgroupForEmulator;
96+virCgroupForVcpu;
97+virCgroupFree;
98+virCgroupGetBlkioWeight;
99+virCgroupGetCpuCfsPeriod;
100+virCgroupGetCpuCfsQuota;
101+virCgroupGetCpuShares;
102+virCgroupGetCpuacctPercpuUsage;
103+virCgroupGetCpuacctStat;
104+virCgroupGetCpuacctUsage;
105+virCgroupGetCpusetCpus;
106+virCgroupGetCpusetMems;
107+virCgroupGetFreezerState;
108+virCgroupGetMemSwapHardLimit;
109+virCgroupGetMemoryHardLimit;
110+virCgroupGetMemorySoftLimit;
111+virCgroupGetMemoryUsage;
112+virCgroupKill;
113+virCgroupKillPainfully;
114+virCgroupKillRecursive;
115+virCgroupMounted;
116+virCgroupMoveTask;
117+virCgroupPathOfController;
118+virCgroupRemove;
119+virCgroupSetBlkioDeviceWeight;
120+virCgroupSetBlkioWeight;
121+virCgroupSetCpuCfsPeriod;
122+virCgroupSetCpuCfsQuota;
123+virCgroupSetCpuShares;
124+virCgroupSetCpusetCpus;
125+virCgroupSetCpusetMems;
126+virCgroupSetFreezerState;
127+virCgroupSetMemSwapHardLimit;
128+virCgroupSetMemory;
129+virCgroupSetMemoryHardLimit;
130+virCgroupSetMemorySoftLimit;
131+
132+
133+# command.h
134+virCommandAbort;
135+virCommandAddArg;
136+virCommandAddArgBuffer;
137+virCommandAddArgFormat;
138+virCommandAddArgList;
139+virCommandAddArgPair;
140+virCommandAddArgSet;
141+virCommandAddEnvBuffer;
142+virCommandAddEnvFormat;
143+virCommandAddEnvPair;
144+virCommandAddEnvPass;
145+virCommandAddEnvPassCommon;
146+virCommandAddEnvString;
147+virCommandAllowCap;
148+virCommandClearCaps;
149+virCommandDaemonize;
150+virCommandExec;
151+virCommandFree;
152+virCommandHandshakeNotify;
153+virCommandHandshakeWait;
154+virCommandNew;
155+virCommandNewArgList;
156+virCommandNewArgs;
157+virCommandNonblockingFDs;
158+virCommandPreserveFD;
159+virCommandRequireHandshake;
160+virCommandRun;
161+virCommandRunAsync;
162+virCommandSetErrorBuffer;
163+virCommandSetErrorFD;
164+virCommandSetInputBuffer;
165+virCommandSetInputFD;
166+virCommandSetOutputBuffer;
167+virCommandSetOutputFD;
168+virCommandSetPidFile;
169+virCommandSetPreExecHook;
170+virCommandSetWorkingDirectory;
171+virCommandToString;
172+virCommandTransferFD;
173+virCommandWait;
174+virCommandWriteArgLog;
175+virFork;
176+virRun;
177+
178+
179+# conf.h
180+virConfFree;
181+virConfFreeValue;
182+virConfGetValue;
183+virConfNew;
184+virConfReadFile;
185+virConfReadMem;
186+virConfSetValue;
187+virConfWriteFile;
188+virConfWriteMem;
189+
190+
191+# cpu.h
192+cpuBaseline;
193+cpuBaselineXML;
194+cpuCompare;
195+cpuCompareXML;
196+cpuDataFree;
197+cpuDecode;
198+cpuEncode;
199+cpuGuestData;
200+cpuHasFeature;
201+cpuMapOverride;
202+cpuNodeData;
203+cpuUpdate;
204+
205+
206+# cpu_conf.h
207+virCPUDefAddFeature;
208+virCPUDefCopy;
209+virCPUDefCopyModel;
210+virCPUDefFormat;
211+virCPUDefFormatBuf;
212+virCPUDefFree;
213+virCPUDefFreeModel;
214+virCPUDefParseXML;
215+virCPUModeTypeToString;
216+
217+
218+# datatypes.h
219+virConnectClass;
220+virDomainClass;
221+virDomainSnapshotClass;
222+virGetConnect;
223+virGetDomain;
224+virGetDomainSnapshot;
225+virGetInterface;
226+virGetNWFilter;
227+virGetNetwork;
228+virGetNodeDevice;
229+virGetSecret;
230+virGetStoragePool;
231+virGetStorageVol;
232+virGetStream;
233+virInterfaceClass;
234+virNetworkClass;
235+virNodeDeviceClass;
236+virNWFilterClass;
237+virSecretClass;
238+virStoragePoolClass;
239+virStorageVolClass;
240+virStreamClass;
241+
242+
243+# device_conf.h
244+virDeviceAddressPciMultiTypeFromString;
245+virDeviceAddressPciMultiTypeToString;
246+virDevicePCIAddressEqual;
247+virDevicePCIAddressFormat;
248+virDevicePCIAddressIsValid;
249+virDevicePCIAddressParseXML;
250+
251+# dnsmasq.h
252+dnsmasqAddDhcpHost;
253+dnsmasqAddHost;
254+dnsmasqContextFree;
255+dnsmasqContextNew;
256+dnsmasqDelete;
257+dnsmasqReload;
258+dnsmasqSave;
259+
260+
261+# domain_audit.h
262+virDomainAuditCgroup;
263+virDomainAuditCgroupMajor;
264+virDomainAuditCgroupPath;
265+virDomainAuditDisk;
266+virDomainAuditFS;
267+virDomainAuditHostdev;
268+virDomainAuditMemory;
269+virDomainAuditNet;
270+virDomainAuditNetDevice;
271+virDomainAuditRedirdev;
272+virDomainAuditSecurityLabel;
273+virDomainAuditStart;
274+virDomainAuditStop;
275+virDomainAuditVcpu;
276+
277+
278+# domain_conf.h
279+virBlkioDeviceWeightArrayClear;
280+virDiskNameToBusDeviceIndex;
281+virDiskNameToIndex;
282+virDomainActualNetDefFree;
283+virDomainAssignDef;
284+virDomainBlockedReasonTypeFromString;
285+virDomainBlockedReasonTypeToString;
286+virDomainBootMenuTypeFromString;
287+virDomainBootMenuTypeToString;
288+virDomainChrConsoleTargetTypeFromString;
289+virDomainChrConsoleTargetTypeToString;
290+virDomainChrDefForeach;
291+virDomainChrDefFree;
292+virDomainChrDefNew;
293+virDomainChrSourceDefCopy;
294+virDomainChrSourceDefFree;
295+virDomainChrSpicevmcTypeFromString;
296+virDomainChrSpicevmcTypeToString;
297+virDomainChrTcpProtocolTypeFromString;
298+virDomainChrTcpProtocolTypeToString;
299+virDomainChrTypeFromString;
300+virDomainChrTypeToString;
301+virDomainClockBasisTypeToString;
302+virDomainClockOffsetTypeFromString;
303+virDomainClockOffsetTypeToString;
304+virDomainConfigFile;
305+virDomainControllerDefFree;
306+virDomainControllerFind;
307+virDomainControllerInsert;
308+virDomainControllerInsertPreAlloced;
309+virDomainControllerModelSCSITypeFromString;
310+virDomainControllerModelSCSITypeToString;
311+virDomainControllerModelUSBTypeFromString;
312+virDomainControllerModelUSBTypeToString;
313+virDomainControllerRemove;
314+virDomainControllerTypeToString;
315+virDomainCpuPlacementModeTypeFromString;
316+virDomainCpuPlacementModeTypeToString;
317+virDomainDefAddImplicitControllers;
318+virDomainDefCheckABIStability;
319+virDomainDefClearDeviceAliases;
320+virDomainDefClearPCIAddresses;
321+virDomainDefCompatibleDevice;
322+virDomainDefFormat;
323+virDomainDefFormatInternal;
324+virDomainDefFree;
325+virDomainDefGetSecurityLabelDef;
326+virDomainDiskDefGetSecurityLabelDef;
327+virDomainDefAddSecurityLabelDef;
328+virDomainDefParseFile;
329+virDomainDefParseNode;
330+virDomainDefParseString;
331+virDomainDeleteConfig;
332+virDomainDeviceAddressIsValid;
333+virDomainDeviceAddressTypeToString;
334+virDomainDeviceDefCopy;
335+virDomainDeviceDefFree;
336+virDomainDeviceDefParse;
337+virDomainDeviceInfoCopy;
338+virDomainDeviceInfoIterate;
339+virDomainDeviceTypeToString;
340+virDomainDiskBusTypeToString;
341+virDomainDiskCacheTypeFromString;
342+virDomainDiskCacheTypeToString;
343+virDomainDiskCopyOnReadTypeFromString;
344+virDomainDiskCopyOnReadTypeToString;
345+virDomainDiskDefAssignAddress;
346+virDomainDiskDefForeachPath;
347+virDomainDiskDefFree;
348+virDomainDiskDeviceTypeToString;
349+virDomainDiskErrorPolicyTypeFromString;
350+virDomainDiskErrorPolicyTypeToString;
351+virDomainDiskFindControllerModel;
352+virDomainDiskGeometryTransTypeFromString;
353+virDomainDiskGeometryTransTypeToString;
354+virDomainDiskIndexByName;
355+virDomainDiskInsert;
356+virDomainDiskInsertPreAlloced;
357+virDomainDiskIoTypeFromString;
358+virDomainDiskIoTypeToString;
359+virDomainDiskPathByName;
360+virDomainDiskRemove;
361+virDomainDiskRemoveByName;
362+virDomainDiskTypeFromString;
363+virDomainDiskTypeToString;
364+virDomainEmulatorPinAdd;
365+virDomainEmulatorPinDel;
366+virDomainFSDefFree;
367+virDomainFSIndexByName;
368+virDomainFSTypeFromString;
369+virDomainFSTypeToString;
370+virDomainFSWrpolicyTypeFromString;
371+virDomainFSWrpolicyTypeToString;
372+virDomainFeatureStateTypeFromString;
373+virDomainFeatureStateTypeToString;
374+virDomainFindByID;
375+virDomainFindByName;
376+virDomainFindByUUID;
377+virDomainGetRootFilesystem;
378+virDomainGraphicsAuthConnectedTypeFromString;
379+virDomainGraphicsAuthConnectedTypeToString;
380+virDomainGraphicsDefFree;
381+virDomainGraphicsListenGetAddress;
382+virDomainGraphicsListenGetNetwork;
383+virDomainGraphicsListenGetType;
384+virDomainGraphicsListenSetAddress;
385+virDomainGraphicsListenSetNetwork;
386+virDomainGraphicsListenSetType;
387+virDomainGraphicsSpiceChannelModeTypeFromString;
388+virDomainGraphicsSpiceChannelModeTypeToString;
389+virDomainGraphicsSpiceChannelNameTypeFromString;
390+virDomainGraphicsSpiceChannelNameTypeToString;
391+virDomainGraphicsSpiceClipboardCopypasteTypeFromString;
392+virDomainGraphicsSpiceClipboardCopypasteTypeToString;
393+virDomainGraphicsSpiceImageCompressionTypeFromString;
394+virDomainGraphicsSpiceImageCompressionTypeToString;
395+virDomainGraphicsSpiceJpegCompressionTypeFromString;
396+virDomainGraphicsSpiceJpegCompressionTypeToString;
397+virDomainGraphicsSpiceMouseModeTypeFromString;
398+virDomainGraphicsSpiceMouseModeTypeToString;
399+virDomainGraphicsSpicePlaybackCompressionTypeFromString;
400+virDomainGraphicsSpicePlaybackCompressionTypeToString;
401+virDomainGraphicsSpiceStreamingModeTypeFromString;
402+virDomainGraphicsSpiceStreamingModeTypeToString;
403+virDomainGraphicsSpiceZlibCompressionTypeFromString;
404+virDomainGraphicsSpiceZlibCompressionTypeToString;
405+virDomainGraphicsTypeFromString;
406+virDomainGraphicsTypeToString;
407+virDomainHasDiskMirror;
408+virDomainHostdevDefAlloc;
409+virDomainHostdevDefClear;
410+virDomainHostdevDefFree;
411+virDomainHostdevFind;
412+virDomainHostdevInsert;
413+virDomainHostdevModeTypeToString;
414+virDomainHostdevRemove;
415+virDomainHostdevSubsysTypeToString;
416+virDomainHubTypeFromString;
417+virDomainHubTypeToString;
418+virDomainHypervTypeFromString;
419+virDomainHypervTypeToString;
420+virDomainInputDefFree;
421+virDomainIoEventFdTypeFromString;
422+virDomainIoEventFdTypeToString;
423+virDomainLeaseDefFree;
424+virDomainLeaseIndex;
425+virDomainLeaseInsert;
426+virDomainLeaseInsertPreAlloc;
427+virDomainLeaseInsertPreAlloced;
428+virDomainLeaseRemove;
429+virDomainLeaseRemoveAt;
430+virDomainLifecycleCrashTypeFromString;
431+virDomainLifecycleCrashTypeToString;
432+virDomainLifecycleTypeFromString;
433+virDomainLifecycleTypeToString;
434+virDomainList;
435+virDomainLiveConfigHelperMethod;
436+virDomainLoadAllConfigs;
437+virDomainLockFailureTypeFromString;
438+virDomainLockFailureTypeToString;
439+virDomainLookupVcpuPin;
440+virDomainMemballoonModelTypeFromString;
441+virDomainMemballoonModelTypeToString;
442+virDomainMemDumpTypeFromString;
443+virDomainMemDumpTypeToString;
444+virDomainNetDefFree;
445+virDomainNetFind;
446+virDomainNetFindIdx;
447+virDomainNetGetActualBandwidth;
448+virDomainNetGetActualBridgeName;
449+virDomainNetGetActualDirectDev;
450+virDomainNetGetActualDirectMode;
451+virDomainNetGetActualHostdev;
452+virDomainNetGetActualType;
453+virDomainNetGetActualVirtPortProfile;
454+virDomainNetGetActualVlan;
455+virDomainNetInsert;
456+virDomainNetRemove;
457+virDomainNetTypeToString;
458+virDomainNostateReasonTypeFromString;
459+virDomainNostateReasonTypeToString;
460+virDomainNumatuneMemModeTypeFromString;
461+virDomainNumatuneMemModeTypeToString;
462+virDomainNumatuneMemPlacementModeTypeFromString;
463+virDomainNumatuneMemPlacementModeTypeToString;
464+virDomainObjAssignDef;
465+virDomainObjCopyPersistentDef;
466+virDomainObjGetPersistentDef;
467+virDomainObjGetState;
468+virDomainObjIsDuplicate;
469+virDomainObjListDeinit;
470+virDomainObjListGetActiveIDs;
471+virDomainObjListGetInactiveNames;
472+virDomainObjListInit;
473+virDomainObjListNumOfDomains;
474+virDomainObjLock;
475+virDomainObjNew;
476+virDomainObjSetDefTransient;
477+virDomainObjSetState;
478+virDomainObjTaint;
479+virDomainObjUnlock;
480+virDomainPausedReasonTypeFromString;
481+virDomainPausedReasonTypeToString;
482+virDomainPciRombarModeTypeFromString;
483+virDomainPciRombarModeTypeToString;
484+virDomainPMStateTypeFromString;
485+virDomainPMStateTypeToString;
486+virDomainRedirdevBusTypeFromString;
487+virDomainRedirdevBusTypeToString;
488+virDomainRemoveInactive;
489+virDomainRunningReasonTypeFromString;
490+virDomainRunningReasonTypeToString;
491+virDomainSaveConfig;
492+virDomainSaveStatus;
493+virDomainSaveXML;
494+virDomainSeclabelTypeFromString;
495+virDomainSeclabelTypeToString;
496+virDomainShutdownReasonTypeFromString;
497+virDomainShutdownReasonTypeToString;
498+virDomainShutoffReasonTypeFromString;
499+virDomainShutoffReasonTypeToString;
500+virDomainSmartcardDefForeach;
501+virDomainSmartcardDefFree;
502+virDomainSmartcardTypeFromString;
503+virDomainSmartcardTypeToString;
504+virDomainSmbiosModeTypeFromString;
505+virDomainSmbiosModeTypeToString;
506+virDomainSoundDefFree;
507+virDomainSoundModelTypeFromString;
508+virDomainSoundModelTypeToString;
509+virDomainStartupPolicyTypeFromString;
510+virDomainStartupPolicyTypeToString;
511+virDomainStateReasonFromString;
512+virDomainStateReasonToString;
513+virDomainStateTypeFromString;
514+virDomainStateTypeToString;
515+virDomainTaintTypeFromString;
516+virDomainTaintTypeToString;
517+virDomainTimerModeTypeFromString;
518+virDomainTimerModeTypeToString;
519+virDomainTimerNameTypeFromString;
520+virDomainTimerNameTypeToString;
521+virDomainTimerTickpolicyTypeFromString;
522+virDomainTimerTickpolicyTypeToString;
523+virDomainTimerTrackTypeFromString;
524+virDomainTimerTrackTypeToString;
525+virDomainVcpuPinAdd;
526+virDomainVcpuPinDefArrayFree;
527+virDomainVcpuPinDefCopy;
528+virDomainVcpuPinDefFree;
529+virDomainVcpuPinDel;
530+virDomainVcpuPinFindByVcpu;
531+virDomainVcpuPinIsDuplicate;
532+virDomainVideoDefFree;
533+virDomainVideoDefaultRAM;
534+virDomainVideoDefaultType;
535+virDomainVideoTypeFromString;
536+virDomainVideoTypeToString;
537+virDomainVirtTypeToString;
538+virDomainVirtioEventIdxTypeFromString;
539+virDomainVirtioEventIdxTypeToString;
540+virDomainWatchdogActionTypeFromString;
541+virDomainWatchdogActionTypeToString;
542+virDomainWatchdogModelTypeFromString;
543+virDomainWatchdogModelTypeToString;
544+
545+
546+# domain_event.h
547+virDomainEventBalloonChangeNewFromDom;
548+virDomainEventBalloonChangeNewFromObj;
549+virDomainEventBlockJobNewFromObj;
550+virDomainEventBlockJobNewFromDom;
551+virDomainEventControlErrorNewFromDom;
552+virDomainEventControlErrorNewFromObj;
553+virDomainEventDiskChangeNewFromDom;
554+virDomainEventDiskChangeNewFromObj;
555+virDomainEventFree;
556+virDomainEventGraphicsNewFromDom;
557+virDomainEventGraphicsNewFromObj;
558+virDomainEventIOErrorNewFromDom;
559+virDomainEventIOErrorNewFromObj;
560+virDomainEventIOErrorReasonNewFromDom;
561+virDomainEventIOErrorReasonNewFromObj;
562+virDomainEventNew;
563+virDomainEventNewFromDef;
564+virDomainEventNewFromDom;
565+virDomainEventNewFromObj;
566+virDomainEventPMSuspendNewFromDom;
567+virDomainEventPMSuspendNewFromObj;
568+virDomainEventPMWakeupNewFromDom;
569+virDomainEventPMWakeupNewFromObj;
570+virDomainEventRTCChangeNewFromDom;
571+virDomainEventRTCChangeNewFromObj;
572+virDomainEventRebootNew;
573+virDomainEventRebootNewFromDom;
574+virDomainEventRebootNewFromObj;
575+virDomainEventStateDeregister;
576+virDomainEventStateDeregisterID;
577+virDomainEventStateEventID;
578+virDomainEventStateRegister;
579+virDomainEventStateRegisterID;
580+virDomainEventStateFree;
581+virDomainEventStateNew;
582+virDomainEventStateQueue;
583+virDomainEventPMSuspendDiskNewFromDom;
584+virDomainEventPMSuspendDiskNewFromObj;
585+virDomainEventTrayChangeNewFromDom;
586+virDomainEventTrayChangeNewFromObj;
587+virDomainEventWatchdogNewFromDom;
588+virDomainEventWatchdogNewFromObj;
589+
590+
591+# domain_lock.h
592+virDomainLockProcessStart;
593+virDomainLockProcessInquire;
594+virDomainLockProcessPause;
595+virDomainLockProcessResume;
596+virDomainLockDiskAttach;
597+virDomainLockDiskDetach;
598+virDomainLockLeaseAttach;
599+virDomainLockLeaseDetach;
600+
601+
602+# domain_nwfilter.h
603+virDomainConfNWFilterInstantiate;
604+virDomainConfNWFilterRegister;
605+virDomainConfNWFilterTeardown;
606+virDomainConfVMNWFilterTeardown;
607+
608+
609+# ebtables.h
610+ebtablesAddForwardAllowIn;
611+ebtablesAddForwardPolicyReject;
612+ebtablesContextFree;
613+ebtablesContextNew;
614+ebtablesRemoveForwardAllowIn;
615+
616+
617+# event_poll.h
618+virEventPollAddHandle;
619+virEventPollAddTimeout;
620+virEventPollFromNativeEvents;
621+virEventPollInit;
622+virEventPollRemoveHandle;
623+virEventPollRemoveTimeout;
624+virEventPollRunOnce;
625+virEventPollToNativeEvents;
626+virEventPollUpdateHandle;
627+virEventPollUpdateTimeout;
628+
629+
630+# fdstream.h
631+virFDStreamOpen;
632+virFDStreamConnectUNIX;
633+virFDStreamOpenFile;
634+virFDStreamCreateFile;
635+
636+
637+# hash.h
638+virHashAddEntry;
639+virHashCreate;
640+virHashEqual;
641+virHashForEach;
642+virHashFree;
643+virHashGetItems;
644+virHashLookup;
645+virHashRemoveAll;
646+virHashRemoveEntry;
647+virHashRemoveSet;
648+virHashSearch;
649+virHashSize;
650+virHashSteal;
651+virHashTableSize;
652+virHashUpdateEntry;
653+
654+
655+# hooks.h
656+virHookCall;
657+virHookInitialize;
658+virHookPresent;
659+
660+
661+# interface_conf.h
662+virInterfaceAssignDef;
663+virInterfaceDefFormat;
664+virInterfaceDefFree;
665+virInterfaceDefParseFile;
666+virInterfaceDefParseNode;
667+virInterfaceDefParseString;
668+virInterfaceFindByMACString;
669+virInterfaceFindByName;
670+virInterfaceObjListClone;
671+virInterfaceObjListFree;
672+virInterfaceObjLock;
673+virInterfaceObjUnlock;
674+virInterfaceRemove;
675+
676+
677+# iptables.h
678+iptablesAddForwardAllowCross;
679+iptablesAddForwardAllowIn;
680+iptablesAddForwardAllowOut;
681+iptablesAddForwardAllowRelatedIn;
682+iptablesAddForwardMasquerade;
683+iptablesAddForwardRejectIn;
684+iptablesAddForwardRejectOut;
685+iptablesAddOutputFixUdpChecksum;
686+iptablesAddTcpInput;
687+iptablesAddUdpInput;
688+iptablesContextFree;
689+iptablesContextNew;
690+iptablesRemoveForwardAllowCross;
691+iptablesRemoveForwardAllowIn;
692+iptablesRemoveForwardAllowOut;
693+iptablesRemoveForwardAllowRelatedIn;
694+iptablesRemoveForwardMasquerade;
695+iptablesRemoveForwardRejectIn;
696+iptablesRemoveForwardRejectOut;
697+iptablesRemoveOutputFixUdpChecksum;
698+iptablesRemoveTcpInput;
699+iptablesRemoveUdpInput;
700+
701+
702+# json.h
703+virJSONValueArrayAppend;
704+virJSONValueArrayGet;
705+virJSONValueArraySize;
706+virJSONValueFree;
707+virJSONValueFromString;
708+virJSONValueGetBoolean;
709+virJSONValueGetNumberDouble;
710+virJSONValueGetNumberInt;
711+virJSONValueGetNumberLong;
712+virJSONValueGetNumberUint;
713+virJSONValueGetNumberUlong;
714+virJSONValueGetString;
715+virJSONValueIsNull;
716+virJSONValueNewArray;
717+virJSONValueNewBoolean;
718+virJSONValueNewNull;
719+virJSONValueNewNumberDouble;
720+virJSONValueNewNumberInt;
721+virJSONValueNewNumberLong;
722+virJSONValueNewNumberUint;
723+virJSONValueNewNumberUlong;
724+virJSONValueNewObject;
725+virJSONValueNewString;
726+virJSONValueNewStringLen;
727+virJSONValueObjectAppend;
728+virJSONValueObjectAppendBoolean;
729+virJSONValueObjectAppendNull;
730+virJSONValueObjectAppendNumberDouble;
731+virJSONValueObjectAppendNumberInt;
732+virJSONValueObjectAppendNumberLong;
733+virJSONValueObjectAppendNumberUint;
734+virJSONValueObjectAppendNumberUlong;
735+virJSONValueObjectAppendString;
736+virJSONValueObjectGet;
737+virJSONValueObjectGetBoolean;
738+virJSONValueObjectGetKey;
739+virJSONValueObjectGetNumberDouble;
740+virJSONValueObjectGetNumberInt;
741+virJSONValueObjectGetNumberLong;
742+virJSONValueObjectGetNumberUint;
743+virJSONValueObjectGetNumberUlong;
744+virJSONValueObjectGetString;
745+virJSONValueObjectGetValue;
746+virJSONValueObjectHasKey;
747+virJSONValueObjectIsNull;
748+virJSONValueObjectKeysNumber;
749+virJSONValueToString;
750+
751+
752+# libvirt_internal.h
753+virDomainMigrateFinish2;
754+virDomainMigrateFinish;
755+virDomainMigratePerform;
756+virDomainMigratePrepare2;
757+virDomainMigratePrepare;
758+virDomainMigratePrepareTunnel;
759+virDomainMigrateBegin3;
760+virDomainMigratePrepare3;
761+virDomainMigratePrepareTunnel3;
762+virDomainMigratePerform3;
763+virDomainMigrateFinish3;
764+virDomainMigrateConfirm3;
765+virDrvSupportsFeature;
766+virRegisterDeviceMonitor;
767+virRegisterDriver;
768+virRegisterInterfaceDriver;
769+virRegisterNWFilterDriver;
770+virRegisterNetworkDriver;
771+virRegisterSecretDriver;
772+virRegisterStorageDriver;
773+
774+
775+# locking.h
776+virLockManagerAcquire;
777+virLockManagerAddResource;
778+virLockManagerFree;
779+virLockManagerInquire;
780+virLockManagerNew;
781+virLockManagerPluginNew;
782+virLockManagerPluginRef;
783+virLockManagerPluginUnref;
784+virLockManagerPluginUsesState;
785+virLockManagerPluginGetName;
786+virLockManagerRelease;
787+virLockManagerSetPluginDir;
788+
789+
790+# logging.h
791+virLogDefineFilter;
792+virLogDefineOutput;
793+virLogEmergencyDumpAll;
794+virLogGetDefaultPriority;
795+virLogGetFilters;
796+virLogGetNbFilters;
797+virLogGetNbOutputs;
798+virLogGetOutputs;
799+virLogLock;
800+virLogMessage;
801+virLogParseDefaultPriority;
802+virLogParseFilters;
803+virLogParseOutputs;
804+virLogReset;
805+virLogSetBufferSize;
806+virLogSetDefaultPriority;
807+virLogSetFromEnv;
808+virLogUnlock;
809+
810+
811+# memory.h
812+virAlloc;
813+virAllocN;
814+virAllocVar;
815+virExpandN;
816+virFree;
817+virReallocN;
818+virResizeN;
819+virShrinkN;
820+
821+
822+# netdev_bandwidth_conf.h
823+virNetDevBandwidthFormat;
824+virNetDevBandwidthParse;
825+
826+
827+#netdev_vlan_conf.h
828+virNetDevVlanFormat;
829+virNetDevVlanParse;
830+
831+
832+# netdev_vportprofile_conf.h
833+virNetDevVPortProfileFormat;
834+virNetDevVPortProfileParse;
835+virNetDevVPortTypeFromString;
836+virNetDevVPortTypeToString;
837+
838+
839+# network_conf.h
840+virNetworkAssignDef;
841+virNetworkConfigFile;
842+virNetworkConfigChangeSetup;
843+virNetworkDefCopy;
844+virNetworkDefFormat;
845+virNetworkDefFree;
846+virNetworkDefGetIpByIndex;
847+virNetworkDefParseFile;
848+virNetworkDefParseNode;
849+virNetworkDefParseString;
850+virNetworkDeleteConfig;
851+virNetworkFindByName;
852+virNetworkFindByUUID;
853+virNetworkIpDefNetmask;
854+virNetworkIpDefPrefix;
855+virNetworkList;
856+virNetworkLoadAllConfigs;
857+virNetworkObjAssignDef;
858+virNetworkObjFree;
859+virNetworkObjGetPersistentDef;
860+virNetworkObjIsDuplicate;
861+virNetworkObjListFree;
862+virNetworkObjLock;
863+virNetworkObjReplacePersistentDef;
864+virNetworkObjSetDefTransient;
865+virNetworkObjUnlock;
866+virNetworkObjUnsetDefTransient;
867+virNetworkObjUpdate;
868+virNetworkRemoveInactive;
869+virNetworkSaveConfig;
870+virNetworkSaveStatus;
871+virNetworkSetBridgeMacAddr;
872+virNetworkSetBridgeName;
873+virPortGroupFindByName;
874+
875+
876+# node_device_conf.h
877+virNodeDevCapTypeFromString;
878+virNodeDevCapTypeToString;
879+virNodeDevCapsDefFree;
880+virNodeDeviceAssignDef;
881+virNodeDeviceDefFormat;
882+virNodeDeviceDefFree;
883+virNodeDeviceDefParseFile;
884+virNodeDeviceDefParseNode;
885+virNodeDeviceDefParseString;
886+virNodeDeviceFindByName;
887+virNodeDeviceFindBySysfsPath;
888+virNodeDeviceGetParentHost;
889+virNodeDeviceGetWWNs;
890+virNodeDeviceHasCap;
891+virNodeDeviceList;
892+virNodeDeviceObjListFree;
893+virNodeDeviceObjLock;
894+virNodeDeviceObjRemove;
895+virNodeDeviceObjUnlock;
896+
897+
898+# nodeinfo.h
899+nodeCapsInitNUMA;
900+nodeGetCPUBitmap;
901+nodeGetCPUCount;
902+nodeGetCPUMap;
903+nodeGetCPUStats;
904+nodeGetCellsFreeMemory;
905+nodeGetFreeMemory;
906+nodeGetInfo;
907+nodeGetMemoryParameters;
908+nodeGetMemoryStats;
909+nodeSetMemoryParameters;
910+
911+
912+# nwfilter_conf.h
913+virNWFilterCallbackDriversLock;
914+virNWFilterCallbackDriversUnlock;
915+virNWFilterChainSuffixTypeToString;
916+virNWFilterConfLayerInit;
917+virNWFilterConfLayerShutdown;
918+virNWFilterDefFormat;
919+virNWFilterDefFree;
920+virNWFilterDefParseString;
921+virNWFilterInstFiltersOnAllVMs;
922+virNWFilterJumpTargetTypeToString;
923+virNWFilterLoadAllConfigs;
924+virNWFilterLockFilterUpdates;
925+virNWFilterObjAssignDef;
926+virNWFilterObjDeleteDef;
927+virNWFilterObjFindByName;
928+virNWFilterObjFindByUUID;
929+virNWFilterObjListFree;
930+virNWFilterObjLock;
931+virNWFilterObjRemove;
932+virNWFilterObjSaveDef;
933+virNWFilterObjUnlock;
934+virNWFilterPrintStateMatchFlags;
935+virNWFilterPrintTCPFlags;
936+virNWFilterRegisterCallbackDriver;
937+virNWFilterRuleActionTypeToString;
938+virNWFilterRuleDirectionTypeToString;
939+virNWFilterRuleProtocolTypeToString;
940+virNWFilterTestUnassignDef;
941+virNWFilterUnRegisterCallbackDriver;
942+virNWFilterUnlockFilterUpdates;
943+
944+
945+# nwfilter_ipaddrmap
946+virNWFilterIPAddrMapAddIPAddr;
947+virNWFilterIPAddrMapDelIPAddr;
948+virNWFilterIPAddrMapGetIPAddr;
949+virNWFilterIPAddrMapInit;
950+virNWFilterIPAddrMapShutdown;
951+
952+
953+# nwfilter_params.h
954+virNWFilterHashTableCreate;
955+virNWFilterHashTableFree;
956+virNWFilterHashTablePut;
957+virNWFilterHashTablePutAll;
958+virNWFilterHashTableRemoveEntry;
959+virNWFilterVarAccessGetVarName;
960+virNWFilterVarAccessIsAvailable;
961+virNWFilterVarAccessPrint;
962+virNWFilterVarCombIterCreate;
963+virNWFilterVarCombIterFree;
964+virNWFilterVarCombIterGetVarValue;
965+virNWFilterVarCombIterNext;
966+virNWFilterVarValueAddValue;
967+virNWFilterVarValueCopy;
968+virNWFilterVarValueCreateSimple;
969+virNWFilterVarValueCreateSimpleCopyValue;
970+virNWFilterVarValueDelValue;
971+virNWFilterVarValueFree;
972+virNWFilterVarValueGetCardinality;
973+virNWFilterVarValueGetNthValue;
974+virNWFilterVarValueGetSimple;
975+
976+
977+# pci.h
978+pciConfigAddressToSysfsFile;
979+pciDettachDevice;
980+pciDeviceFileIterate;
981+pciDeviceGetManaged;
982+pciDeviceGetName;
983+pciDeviceGetRemoveSlot;
984+pciDeviceGetReprobe;
985+pciDeviceGetUnbindFromStub;
986+pciDeviceGetUsedBy;
987+pciDeviceGetVirtualFunctionInfo;
988+pciDeviceIsAssignable;
989+pciDeviceIsVirtualFunction;
990+pciDeviceListAdd;
991+pciDeviceListCount;
992+pciDeviceListDel;
993+pciDeviceListFind;
994+pciDeviceListFree;
995+pciDeviceListGet;
996+pciDeviceListNew;
997+pciDeviceListSteal;
998+pciDeviceNetName;
999+pciDeviceReAttachInit;
1000+pciDeviceSetManaged;
1001+pciDeviceSetRemoveSlot;
1002+pciDeviceSetReprobe;
1003+pciDeviceSetUnbindFromStub;
1004+pciDeviceSetUsedBy;
1005+pciFreeDevice;
1006+pciGetDevice;
1007+pciGetPhysicalFunction;
1008+pciGetVirtualFunctionIndex;
1009+pciGetVirtualFunctions;
1010+pciReAttachDevice;
1011+pciResetDevice;
1012+pciWaitForDeviceCleanup;
1013+
1014+
1015+# processinfo.h
1016+virProcessInfoGetAffinity;
1017+virProcessInfoSetAffinity;
1018+
1019+
1020+# secret_conf.h
1021+virSecretDefFormat;
1022+virSecretDefFree;
1023+virSecretDefParseFile;
1024+virSecretDefParseString;
1025+virSecretUsageTypeTypeFromString;
1026+virSecretUsageTypeTypeToString;
1027+
1028+
1029+# security_driver.h
1030+virSecurityDriverLookup;
1031+
1032+
1033+# security_manager.h
1034+virSecurityManagerClearSocketLabel;
1035+virSecurityManagerFree;
1036+virSecurityManagerGenLabel;
1037+virSecurityManagerGetDOI;
1038+virSecurityManagerGetModel;
1039+virSecurityManagerGetNested;
1040+virSecurityManagerGetProcessLabel;
1041+virSecurityManagerNew;
1042+virSecurityManagerNewStack;
1043+virSecurityManagerNewDAC;
1044+virSecurityManagerReleaseLabel;
1045+virSecurityManagerReserveLabel;
1046+virSecurityManagerRestoreImageLabel;
1047+virSecurityManagerRestoreAllLabel;
1048+virSecurityManagerRestoreHostdevLabel;
1049+virSecurityManagerRestoreSavedStateLabel;
1050+virSecurityManagerSetAllLabel;
1051+virSecurityManagerSetDaemonSocketLabel;
1052+virSecurityManagerSetImageFDLabel;
1053+virSecurityManagerSetImageLabel;
1054+virSecurityManagerSetHostdevLabel;
1055+virSecurityManagerSetProcessLabel;
1056+virSecurityManagerSetSavedStateLabel;
1057+virSecurityManagerSetSocketLabel;
1058+virSecurityManagerSetTapFDLabel;
1059+virSecurityManagerStackAddNested;
1060+virSecurityManagerVerify;
1061+virSecurityManagerGetMountOptions;
1062+
1063+# sexpr.h
1064+sexpr_append;
1065+sexpr_cons;
1066+sexpr_float;
1067+sexpr_fmt_node;
1068+sexpr_free;
1069+sexpr_has;
1070+sexpr_int;
1071+sexpr_lookup;
1072+sexpr_nil;
1073+sexpr_node;
1074+sexpr_node_copy;
1075+sexpr_string;
1076+sexpr_u64;
1077+sexpr2string;
1078+string2sexpr;
1079+
1080+
1081+# snapshot_conf.h
1082+virDomainListSnapshots;
1083+virDomainSnapshotAlignDisks;
1084+virDomainSnapshotAssignDef;
1085+virDomainSnapshotDefFormat;
1086+virDomainSnapshotDefFree;
1087+virDomainSnapshotDefParseString;
1088+virDomainSnapshotDropParent;
1089+virDomainSnapshotFindByName;
1090+virDomainSnapshotForEach;
1091+virDomainSnapshotForEachChild;
1092+virDomainSnapshotForEachDescendant;
1093+virDomainSnapshotLocationTypeFromString;
1094+virDomainSnapshotLocationTypeToString;
1095+virDomainSnapshotObjListGetNames;
1096+virDomainSnapshotObjListNum;
1097+virDomainSnapshotObjListRemove;
1098+virDomainSnapshotStateTypeFromString;
1099+virDomainSnapshotStateTypeToString;
1100+virDomainSnapshotUpdateRelations;
1101+
1102+
1103+# storage_conf.h
1104+virStoragePartedFsTypeTypeToString;
1105+virStoragePoolDefFormat;
1106+virStoragePoolDefFree;
1107+virStoragePoolDefParseFile;
1108+virStoragePoolDefParseNode;
1109+virStoragePoolDefParseSourceString;
1110+virStoragePoolDefParseString;
1111+virStoragePoolFormatDiskTypeToString;
1112+virStoragePoolFormatFileSystemNetTypeToString;
1113+virStoragePoolFormatFileSystemTypeToString;
1114+virStoragePoolList;
1115+virStoragePoolLoadAllConfigs;
1116+virStoragePoolObjAssignDef;
1117+virStoragePoolObjClearVols;
1118+virStoragePoolObjDeleteDef;
1119+virStoragePoolObjFindByName;
1120+virStoragePoolObjFindByUUID;
1121+virStoragePoolObjIsDuplicate;
1122+virStoragePoolObjListFree;
1123+virStoragePoolObjLock;
1124+virStoragePoolObjRemove;
1125+virStoragePoolObjSaveDef;
1126+virStoragePoolObjUnlock;
1127+virStoragePoolSourceClear;
1128+virStoragePoolSourceFindDuplicate;
1129+virStoragePoolSourceFindDuplicateDevices;
1130+virStoragePoolSourceFree;
1131+virStoragePoolSourceListFormat;
1132+virStoragePoolSourceListNewSource;
1133+virStoragePoolTypeFromString;
1134+virStorageVolDefFindByKey;
1135+virStorageVolDefFindByName;
1136+virStorageVolDefFindByPath;
1137+virStorageVolDefFormat;
1138+virStorageVolDefFree;
1139+virStorageVolDefParseFile;
1140+virStorageVolDefParseNode;
1141+virStorageVolDefParseString;
1142+
1143+
1144+# storage_encryption_conf.h
1145+virStorageEncryptionFormat;
1146+virStorageEncryptionFree;
1147+virStorageEncryptionParseNode;
1148+virStorageGenerateQcowPassphrase;
1149+
1150+
1151+# storage_file.h
1152+virStorageFileChainLookup;
1153+virStorageFileFormatTypeFromString;
1154+virStorageFileFormatTypeToString;
1155+virStorageFileFreeMetadata;
1156+virStorageFileGetMetadata;
1157+virStorageFileGetMetadataFromFD;
1158+virStorageFileIsClusterFS;
1159+virStorageFileIsSharedFS;
1160+virStorageFileIsSharedFSType;
1161+virStorageFileProbeFormat;
1162+virStorageFileProbeFormatFromFD;
1163+virStorageFileResize;
1164+
1165+# sysinfo.h
1166+virSysinfoDefFree;
1167+virSysinfoFormat;
1168+virSysinfoRead;
1169+
1170+
1171+# threadpool.h
1172+virThreadPoolFree;
1173+virThreadPoolNew;
1174+virThreadPoolSendJob;
1175+virThreadPoolGetMinWorkers;
1176+virThreadPoolGetMaxWorkers;
1177+virThreadPoolGetPriorityWorkers;
1178+
1179+
1180+# threads.h
1181+virCondBroadcast;
1182+virCondDestroy;
1183+virCondInit;
1184+virCondSignal;
1185+virCondWait;
1186+virCondWaitUntil;
1187+virMutexDestroy;
1188+virMutexInit;
1189+virMutexInitRecursive;
1190+virMutexLock;
1191+virMutexUnlock;
1192+virOnce;
1193+virThreadCreate;
1194+virThreadID;
1195+virThreadInitialize;
1196+virThreadIsSelf;
1197+virThreadJoin;
1198+virThreadSelf;
1199+virThreadSelfID;
1200+
1201+
1202+# usb.h
1203+usbDeviceFileIterate;
1204+usbDeviceGetBus;
1205+usbDeviceGetDevno;
1206+usbDeviceGetName;
1207+usbDeviceGetUsedBy;
1208+usbDeviceListAdd;
1209+usbDeviceListCount;
1210+usbDeviceListDel;
1211+usbDeviceListFind;
1212+usbDeviceListFree;
1213+usbDeviceListGet;
1214+usbDeviceListNew;
1215+usbDeviceListSteal;
1216+usbDeviceSetUsedBy;
1217+usbFindDevice;
1218+usbFindDeviceByBus;
1219+usbFindDeviceByVendor;
1220+usbFreeDevice;
1221+usbGetDevice;
1222+
1223+
1224+# util.h
1225+saferead;
1226+safewrite;
1227+safezero;
1228+virArgvToString;
1229+virAsprintf;
1230+virBuildPathInternal;
1231+virDirCreate;
1232+virDoubleToStr;
1233+virEnumFromString;
1234+virEnumToString;
1235+virFileAbsPath;
1236+virFileAccessibleAs;
1237+virFileBuildPath;
1238+virFileExists;
1239+virFileFindMountPoint;
1240+virFileHasSuffix;
1241+virFileIsAbsPath;
1242+virFileIsExecutable;
1243+virFileIsLink;
1244+virFileIsDir;
1245+virFileLinkPointsTo;
1246+virFileLock;
1247+virFileMakePath;
1248+virFileMakePathWithMode;
1249+virFileMatchesNameSuffix;
1250+virFileOpenAs;
1251+virFileOpenTty;
1252+virFileReadAll;
1253+virFileReadLimFD;
1254+virFileResolveAllLinks;
1255+virFileResolveLink;
1256+virFileSanitizePath;
1257+virFileSkipRoot;
1258+virFileStripSuffix;
1259+virFileUnlock;
1260+virFileWaitForDevices;
1261+virFileWriteStr;
1262+virFindFileInPath;
1263+virFormatIntDecimal;
1264+virGetGroupID;
1265+virGetGroupName;
1266+virGetHostname;
1267+virGetUserDirectory;
1268+virGetUserConfigDirectory;
1269+virGetUserCacheDirectory;
1270+virGetUserRuntimeDirectory;
1271+virGetUserID;
1272+virGetUserName;
1273+virHexToBin;
1274+virIndexToDiskName;
1275+virIsDevMapperDevice;
1276+virParseNumber;
1277+virParseVersionString;
1278+virPipeReadUntilEOF;
1279+virScaleInteger;
1280+virSetBlocking;
1281+virSetCloseExec;
1282+virSetInherit;
1283+virSetNonBlock;
1284+virSetUIDGID;
1285+virSkipSpaces;
1286+virSkipSpacesAndBackslash;
1287+virSkipSpacesBackwards;
1288+virStrToDouble;
1289+virStrToLong_i;
1290+virStrToLong_l;
1291+virStrToLong_ll;
1292+virStrToLong_ui;
1293+virStrToLong_ul;
1294+virStrToLong_ull;
1295+virStrcpy;
1296+virStrncpy;
1297+virTrimSpaces;
1298+virValidateWWN;
1299+virVasprintf;
1300+
1301+
1302+# uuid.h
1303+virGetHostUUID;
1304+virSetHostUUIDStr;
1305+virUUIDFormat;
1306+virUUIDGenerate;
1307+virUUIDIsValid;
1308+virUUIDParse;
1309+
1310+
1311+# virauth.h
1312+virAuthGetConfigFilePath;
1313+virAuthGetPassword;
1314+virAuthGetUsername;
1315+
1316+
1317+# virauthconfig.h
1318+virAuthConfigFree;
1319+virAuthConfigLookup;
1320+virAuthConfigNew;
1321+virAuthConfigNewData;
1322+
1323+
1324+# viraudit.h
1325+virAuditClose;
1326+virAuditEncode;
1327+virAuditLog;
1328+virAuditOpen;
1329+virAuditSend;
1330+
1331+
1332+# virconsole.h
1333+virConsoleAlloc;
1334+virConsoleFree;
1335+virConsoleOpen;
1336+
1337+
1338+# virdbus.h
1339+virDBusGetSystemBus;
1340+
1341+
1342+# virfile.h
1343+virFileLoopDeviceAssociate;
1344+virFileClose;
1345+virFileDirectFdFlag;
1346+virFileWrapperFdCatchError;
1347+virFileWrapperFdClose;
1348+virFileWrapperFdFree;
1349+virFileWrapperFdNew;
1350+virFileFclose;
1351+virFileFdopen;
1352+virFileRewrite;
1353+virFileTouch;
1354+virFileUpdatePerm;
1355+
1356+
1357+# virkeycode.h
1358+virKeycodeSetTypeFromString;
1359+virKeycodeSetTypeToString;
1360+virKeycodeValueFromString;
1361+virKeycodeValueTranslate;
1362+
1363+
1364+# virkeyfile.h
1365+virKeyFileNew;
1366+virKeyFileLoadFile;
1367+virKeyFileLoadData;
1368+virKeyFileFree;
1369+virKeyFileHasValue;
1370+virKeyFileHasGroup;
1371+virKeyFileGetValueString;
1372+
1373+
1374+# virlockspace.h
1375+virLockSpaceAcquireResource;
1376+virLockSpaceCreateResource;
1377+virLockSpaceDeleteResource;
1378+virLockSpaceFree;
1379+virLockSpaceGetDirectory;
1380+virLockSpaceNew;
1381+virLockSpaceNewPostExecRestart;
1382+virLockSpacePreExecRestart;
1383+virLockSpaceReleaseResource;
1384+virLockSpaceReleaseResourcesForOwner;
1385+
1386+
1387+# virmacaddr.h
1388+virMacAddrCmp;
1389+virMacAddrCmpRaw;
1390+virMacAddrCompare;
1391+virMacAddrFormat;
1392+virMacAddrGenerate;
1393+virMacAddrGetRaw;
1394+virMacAddrIsBroadcastRaw;
1395+virMacAddrIsMulticast;
1396+virMacAddrIsUnicast;
1397+virMacAddrParse;
1398+virMacAddrSet;
1399+virMacAddrSetRaw;
1400+
1401+
1402+# virnetclient.h
1403+virNetClientAddProgram;
1404+virNetClientAddStream;
1405+virNetClientClose;
1406+virNetClientDupFD;
1407+virNetClientGetFD;
1408+virNetClientGetTLSKeySize;
1409+virNetClientHasPassFD;
1410+virNetClientIsEncrypted;
1411+virNetClientIsOpen;
1412+virNetClientKeepAliveIsSupported;
1413+virNetClientKeepAliveStart;
1414+virNetClientKeepAliveStop;
1415+virNetClientLocalAddrString;
1416+virNetClientNewExternal;
1417+virNetClientNewLibSSH2;
1418+virNetClientNewSSH;
1419+virNetClientNewTCP;
1420+virNetClientNewUNIX;
1421+virNetClientRegisterAsyncIO;
1422+virNetClientRegisterKeepAlive;
1423+virNetClientRemoteAddrString;
1424+virNetClientRemoveStream;
1425+virNetClientSendNoReply;
1426+virNetClientSendNonBlock;
1427+virNetClientSendWithReply;
1428+virNetClientSendWithReplyStream;
1429+virNetClientSetCloseCallback;
1430+virNetClientSetTLSSession;
1431+
1432+
1433+# virnetclientprogram.h
1434+virNetClientProgramCall;
1435+virNetClientProgramDispatch;
1436+virNetClientProgramGetProgram;
1437+virNetClientProgramGetVersion;
1438+virNetClientProgramMatches;
1439+virNetClientProgramNew;
1440+
1441+
1442+# virnetclientstream.h
1443+virNetClientStreamEOF;
1444+virNetClientStreamEventAddCallback;
1445+virNetClientStreamEventRemoveCallback;
1446+virNetClientStreamEventUpdateCallback;
1447+virNetClientStreamMatches;
1448+virNetClientStreamNew;
1449+virNetClientStreamQueuePacket;
1450+virNetClientStreamRaiseError;
1451+virNetClientStreamRecvPacket;
1452+virNetClientStreamSendPacket;
1453+virNetClientStreamSetError;
1454+
1455+
1456+# virnetdev.h
1457+virNetDevClearIPv4Address;
1458+virNetDevExists;
1459+virNetDevGetIPv4Address;
1460+virNetDevGetIndex;
1461+virNetDevGetMAC;
1462+virNetDevGetMTU;
1463+virNetDevGetPhysicalFunction;
1464+virNetDevGetVLanID;
1465+virNetDevGetVirtualFunctionIndex;
1466+virNetDevGetVirtualFunctionInfo;
1467+virNetDevGetVirtualFunctions;
1468+virNetDevIsOnline;
1469+virNetDevIsVirtualFunction;
1470+virNetDevLinkDump;
1471+virNetDevReplaceMacAddress;
1472+virNetDevReplaceNetConfig;
1473+virNetDevRestoreMacAddress;
1474+virNetDevRestoreNetConfig;
1475+virNetDevSetIPv4Address;
1476+virNetDevSetMAC;
1477+virNetDevSetMTU;
1478+virNetDevSetMTUFromDevice;
1479+virNetDevSetName;
1480+virNetDevSetNamespace;
1481+virNetDevSetOnline;
1482+virNetDevValidateConfig;
1483+
1484+
1485+# virnetdevbandwidth.h
1486+virNetDevBandwidthClear;
1487+virNetDevBandwidthCopy;
1488+virNetDevBandwidthEqual;
1489+virNetDevBandwidthFree;
1490+virNetDevBandwidthSet;
1491+
1492+
1493+# virnetdevbridge.h
1494+virNetDevBridgeAddPort;
1495+virNetDevBridgeCreate;
1496+virNetDevBridgeDelete;
1497+virNetDevBridgeGetSTP;
1498+virNetDevBridgeGetSTPDelay;
1499+virNetDevBridgeRemovePort;
1500+virNetDevBridgeSetSTP;
1501+virNetDevBridgeSetSTPDelay;
1502+
1503+
1504+# virnetdevmacvlan.h
1505+virNetDevMacVLanCreate;
1506+virNetDevMacVLanDelete;
1507+virNetDevMacVLanCreateWithVPortProfile;
1508+virNetDevMacVLanDeleteWithVPortProfile;
1509+virNetDevMacVLanRestartWithVPortProfile;
1510+virNetDevMacVLanVPortProfileRegisterCallback;
1511+
1512+
1513+# virnetdevopenvswitch.h
1514+virNetDevOpenvswitchAddPort;
1515+virNetDevOpenvswitchGetMigrateData;
1516+virNetDevOpenvswitchRemovePort;
1517+virNetDevOpenvswitchSetMigrateData;
1518+
1519+
1520+# virnetdevtap.h
1521+virNetDevTapCreate;
1522+virNetDevTapCreateInBridgePort;
1523+virNetDevTapDelete;
1524+
1525+
1526+# virnetdevveth.h
1527+virNetDevVethCreate;
1528+virNetDevVethDelete;
1529+
1530+
1531+# virnetdevvlan.h
1532+virNetDevVlanClear;
1533+virNetDevVlanCopy;
1534+virNetDevVlanEqual;
1535+virNetDevVlanFree;
1536+
1537+# virnetdevvportprofile.h
1538+virNetDevVPortProfileAssociate;
1539+virNetDevVPortProfileCheckComplete;
1540+virNetDevVPortProfileCheckNoExtras;
1541+virNetDevVPortProfileDisassociate;
1542+virNetDevVPortProfileEqual;
1543+virNetDevVPortProfileMerge3;
1544+virNetDevVPortProfileOpTypeFromString;
1545+virNetDevVPortProfileOpTypeToString;
1546+
1547+
1548+#virnetlink.h
1549+virNetlinkCommand;
1550+virNetlinkEventAddClient;
1551+virNetlinkEventRemoveClient;
1552+virNetlinkEventServiceIsRunning;
1553+virNetlinkEventServiceLocalPid;
1554+virNetlinkEventServiceStop;
1555+virNetlinkEventServiceStopAll;
1556+virNetlinkEventServiceStart;
1557+virNetlinkShutdown;
1558+virNetlinkStartup;
1559+
1560+
1561+# virnetmessage.h
1562+virNetMessageClear;
1563+virNetMessageDecodeHeader;
1564+virNetMessageDecodeNumFDs;
1565+virNetMessageDecodeLength;
1566+virNetMessageDecodePayload;
1567+virNetMessageDupFD;
1568+virNetMessageEncodeHeader;
1569+virNetMessageEncodePayload;
1570+virNetMessageEncodePayloadRaw;
1571+virNetMessageEncodeNumFDs;
1572+virNetMessageFree;
1573+virNetMessageNew;
1574+virNetMessageQueuePush;
1575+virNetMessageQueueServe;
1576+virNetMessageSaveError;
1577+xdr_virNetMessageError;
1578+
1579+
1580+# virnetserver.h
1581+virNetServerAddProgram;
1582+virNetServerAddService;
1583+virNetServerAddSignalHandler;
1584+virNetServerAutoShutdown;
1585+virNetServerClose;
1586+virNetServerIsPrivileged;
1587+virNetServerKeepAliveRequired;
1588+virNetServerNew;
1589+virNetServerNewPostExecRestart;
1590+virNetServerPreExecRestart;
1591+virNetServerQuit;
1592+virNetServerRun;
1593+virNetServerSetTLSContext;
1594+virNetServerUpdateServices;
1595+
1596+
1597+# virnetserverclient.h
1598+virNetServerClientAddFilter;
1599+virNetServerClientClose;
1600+virNetServerClientDelayedClose;
1601+virNetServerClientGetAuth;
1602+virNetServerClientGetFD;
1603+virNetServerClientGetIdentity;
1604+virNetServerClientGetPrivateData;
1605+virNetServerClientGetReadonly;
1606+virNetServerClientGetTLSKeySize;
1607+virNetServerClientGetUNIXIdentity;
1608+virNetServerClientHasTLSSession;
1609+virNetServerClientImmediateClose;
1610+virNetServerClientInit;
1611+virNetServerClientInitKeepAlive;
1612+virNetServerClientIsClosed;
1613+virNetServerClientIsSecure;
1614+virNetServerClientLocalAddrString;
1615+virNetServerClientNeedAuth;
1616+virNetServerClientNew;
1617+virNetServerClientNewPostExecRestart;
1618+virNetServerClientPreExecRestart;
1619+virNetServerClientRemoteAddrString;
1620+virNetServerClientRemoveFilter;
1621+virNetServerClientSendMessage;
1622+virNetServerClientSetCloseHook;
1623+virNetServerClientSetDispatcher;
1624+virNetServerClientSetIdentity;
1625+virNetServerClientStartKeepAlive;
1626+virNetServerClientWantClose;
1627+
1628+
1629+# virnetservermdns.h
1630+virNetServerMDNSAddEntry;
1631+virNetServerMDNSAddGroup;
1632+virNetServerMDNSEntryFree;
1633+virNetServerMDNSFree;
1634+virNetServerMDNSGroupFree;
1635+virNetServerMDNSNew;
1636+virNetServerMDNSRemoveEntry;
1637+virNetServerMDNSRemoveGroup;
1638+virNetServerMDNSStart;
1639+virNetServerMDNSStop;
1640+
1641+
1642+# virnetserverprogram.h
1643+virNetServerProgramDispatch;
1644+virNetServerProgramGetID;
1645+virNetServerProgramGetPriority;
1646+virNetServerProgramGetVersion;
1647+virNetServerProgramMatches;
1648+virNetServerProgramNew;
1649+virNetServerProgramSendReplyError;
1650+virNetServerProgramSendStreamData;
1651+virNetServerProgramSendStreamError;
1652+virNetServerProgramUnknownError;
1653+
1654+
1655+# virnetserverservice.h
1656+virNetServerServiceClose;
1657+virNetServerServiceGetAuth;
1658+virNetServerServiceGetMaxRequests;
1659+virNetServerServiceGetPort;
1660+virNetServerServiceGetTLSContext;
1661+virNetServerServiceIsReadonly;
1662+virNetServerServiceNewFD;
1663+virNetServerServiceNewPostExecRestart;
1664+virNetServerServiceNewTCP;
1665+virNetServerServiceNewUNIX;
1666+virNetServerServicePreExecRestart;
1667+virNetServerServiceSetDispatcher;
1668+virNetServerServiceToggle;
1669+
1670+
1671+# virnetsocket.h
1672+virNetSocketAccept;
1673+virNetSocketAddIOCallback;
1674+virNetSocketClose;
1675+virNetSocketDupFD;
1676+virNetSocketGetFD;
1677+virNetSocketGetPort;
1678+virNetSocketGetUNIXIdentity;
1679+virNetSocketHasCachedData;
1680+virNetSocketHasPassFD;
1681+virNetSocketHasPendingData;
1682+virNetSocketIsLocal;
1683+virNetSocketListen;
1684+virNetSocketLocalAddrString;
1685+virNetSocketNewConnectCommand;
1686+virNetSocketNewConnectExternal;
1687+virNetSocketNewConnectLibSSH2;
1688+virNetSocketNewConnectSSH;
1689+virNetSocketNewConnectTCP;
1690+virNetSocketNewConnectUNIX;
1691+virNetSocketNewListenFD;
1692+virNetSocketNewListenTCP;
1693+virNetSocketNewListenUNIX;
1694+virNetSocketNewPostExecRestart;
1695+virNetSocketPreExecRestart;
1696+virNetSocketRead;
1697+virNetSocketRecvFD;
1698+virNetSocketRemoteAddrString;
1699+virNetSocketRemoveIOCallback;
1700+virNetSocketSendFD;
1701+virNetSocketSetBlocking;
1702+virNetSocketSetTLSSession;
1703+virNetSocketUpdateIOCallback;
1704+virNetSocketWrite;
1705+
1706+
1707+# virnettlscontext.h
1708+virNetTLSContextCheckCertificate;
1709+virNetTLSContextNewClient;
1710+virNetTLSContextNewClientPath;
1711+virNetTLSContextNewServer;
1712+virNetTLSContextNewServerPath;
1713+virNetTLSInit;
1714+virNetTLSSessionGetHandshakeStatus;
1715+virNetTLSSessionGetKeySize;
1716+virNetTLSSessionHandshake;
1717+virNetTLSSessionNew;
1718+virNetTLSSessionRead;
1719+virNetTLSSessionSetIOCallbacks;
1720+virNetTLSSessionWrite;
1721+
1722+
1723+# virnodesuspend.h
1724+nodeSuspendForDuration;
1725+virNodeSuspendGetTargetMask;
1726+
1727+
1728+# virobject.h
1729+virClassName;
1730+virClassNew;
1731+virObjectFreeCallback;
1732+virObjectIsClass;
1733+virObjectNew;
1734+virObjectRef;
1735+virObjectUnref;
1736+
1737+
1738+# virpidfile.h
1739+virPidFileAcquire;
1740+virPidFileAcquirePath;
1741+virPidFileBuildPath;
1742+virPidFileRead;
1743+virPidFileReadIfAlive;
1744+virPidFileReadPath;
1745+virPidFileReadPathIfAlive;
1746+virPidFileRelease;
1747+virPidFileReleasePath;
1748+virPidFileWrite;
1749+virPidFileWritePath;
1750+virPidFileDelete;
1751+virPidFileDeletePath;
1752+
1753+
1754+# virprocess.h
1755+virProcessAbort;
1756+virProcessKill;
1757+virProcessKillPainfully;
1758+virProcessTranslateStatus;
1759+virProcessWait;
1760+
1761+
1762+# virrandom.h
1763+virRandom;
1764+virRandomBits;
1765+virRandomGenerateWWN;
1766+virRandomInt;
1767+
1768+
1769+# virsocketaddr.h
1770+virSocketAddrBroadcast;
1771+virSocketAddrBroadcastByPrefix;
1772+virSocketAddrCheckNetmask;
1773+virSocketAddrEqual;
1774+virSocketAddrFormat;
1775+virSocketAddrFormatFull;
1776+virSocketAddrGetPort;
1777+virSocketAddrGetRange;
1778+virSocketAddrIsNetmask;
1779+virSocketAddrMask;
1780+virSocketAddrMaskByPrefix;
1781+virSocketAddrParse;
1782+virSocketAddrParseIPv4;
1783+virSocketAddrParseIPv6;
1784+virSocketAddrPrefixToNetmask;
1785+virSocketAddrSetIPv4Addr;
1786+virSocketAddrSetPort;
1787+
1788+
1789+# virterror_internal.h
1790+virDispatchError;
1791+virErrorInitialize;
1792+virRaiseErrorFull;
1793+virReportErrorHelper;
1794+virReportOOMErrorFull;
1795+virReportSystemErrorFull;
1796+virSetError;
1797+virSetErrorLogPriorityFunc;
1798+virStrerror;
1799+
1800+
1801+# virtime.h
1802+virTimeFieldsNow;
1803+virTimeFieldsNowRaw;
1804+virTimeFieldsThen;
1805+virTimeFieldsThenRaw;
1806+virTimeMillisNow;
1807+virTimeMillisNowRaw;
1808+virTimeStringNow;
1809+virTimeStringNowRaw;
1810+virTimeStringThen;
1811+virTimeStringThenRaw;
1812+
1813+
1814+# virtypedparam.h
1815+virTypedParameterArrayClear;
1816+virTypedParameterArrayValidate;
1817+virTypedParameterAssign;
1818+virTypedParameterAssignFromStr;
1819+
1820+
1821+# viruri.h
1822+virURIFormat;
1823+virURIFormatParams;
1824+virURIFree;
1825+virURIParse;
1826+
1827+
1828+# xml.h
1829+virXMLChildElementCount;
1830+virXMLParseHelper;
1831+virXMLPickShellSafeComment;
1832+virXMLPropString;
1833+virXMLSaveFile;
1834+virXPathBoolean;
1835+virXPathInt;
1836+virXPathLong;
1837+virXPathLongHex;
1838+virXPathLongLong;
1839+virXPathNode;
1840+virXPathNodeSet;
1841+virXPathNumber;
1842+virXPathString;
1843+virXPathStringLimit;
1844+virXPathUInt;
1845+virXPathULong;
1846+virXPathULongHex;
1847+virXPathULongLong;
1848
1849=== added directory '.pc/apparmor-allow-hugepages/src/qemu'
1850=== added file '.pc/apparmor-allow-hugepages/src/qemu/qemu_process.c'
1851--- .pc/apparmor-allow-hugepages/src/qemu/qemu_process.c 1970-01-01 00:00:00 +0000
1852+++ .pc/apparmor-allow-hugepages/src/qemu/qemu_process.c 2012-12-11 20:02:29 +0000
1853@@ -0,0 +1,4474 @@
1854+/*
1855+ * qemu_process.h: QEMU process management
1856+ *
1857+ * Copyright (C) 2006-2012 Red Hat, Inc.
1858+ *
1859+ * This library is free software; you can redistribute it and/or
1860+ * modify it under the terms of the GNU Lesser General Public
1861+ * License as published by the Free Software Foundation; either
1862+ * version 2.1 of the License, or (at your option) any later version.
1863+ *
1864+ * This library is distributed in the hope that it will be useful,
1865+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1866+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1867+ * Lesser General Public License for more details.
1868+ *
1869+ * You should have received a copy of the GNU Lesser General Public
1870+ * License along with this library. If not, see
1871+ * <http://www.gnu.org/licenses/>.
1872+ *
1873+ */
1874+
1875+#include <config.h>
1876+
1877+#include <fcntl.h>
1878+#include <unistd.h>
1879+#include <signal.h>
1880+#include <sys/stat.h>
1881+#include <sys/time.h>
1882+#include <sys/resource.h>
1883+#include <linux/capability.h>
1884+
1885+#include "qemu_process.h"
1886+#include "qemu_domain.h"
1887+#include "qemu_cgroup.h"
1888+#include "qemu_capabilities.h"
1889+#include "qemu_monitor.h"
1890+#include "qemu_command.h"
1891+#include "qemu_hostdev.h"
1892+#include "qemu_hotplug.h"
1893+#include "qemu_bridge_filter.h"
1894+#include "qemu_migration.h"
1895+
1896+#if HAVE_NUMACTL
1897+# define NUMA_VERSION1_COMPATIBILITY 1
1898+# include <numa.h>
1899+#endif
1900+
1901+#include "datatypes.h"
1902+#include "logging.h"
1903+#include "virterror_internal.h"
1904+#include "memory.h"
1905+#include "hooks.h"
1906+#include "virfile.h"
1907+#include "virpidfile.h"
1908+#include "util.h"
1909+#include "c-ctype.h"
1910+#include "nodeinfo.h"
1911+#include "processinfo.h"
1912+#include "domain_audit.h"
1913+#include "domain_nwfilter.h"
1914+#include "locking/domain_lock.h"
1915+#include "network/bridge_driver.h"
1916+#include "uuid.h"
1917+#include "virprocess.h"
1918+#include "virtime.h"
1919+#include "virnetdevtap.h"
1920+#include "bitmap.h"
1921+
1922+#define VIR_FROM_THIS VIR_FROM_QEMU
1923+
1924+#define START_POSTFIX ": starting up\n"
1925+#define ATTACH_POSTFIX ": attaching\n"
1926+#define SHUTDOWN_POSTFIX ": shutting down\n"
1927+
1928+/**
1929+ * qemudRemoveDomainStatus
1930+ *
1931+ * remove all state files of a domain from statedir
1932+ *
1933+ * Returns 0 on success
1934+ */
1935+static int
1936+qemuProcessRemoveDomainStatus(struct qemud_driver *driver,
1937+ virDomainObjPtr vm)
1938+{
1939+ char ebuf[1024];
1940+ char *file = NULL;
1941+ qemuDomainObjPrivatePtr priv = vm->privateData;
1942+
1943+ if (virAsprintf(&file, "%s/%s.xml", driver->stateDir, vm->def->name) < 0) {
1944+ virReportOOMError();
1945+ return -1;
1946+ }
1947+
1948+ if (unlink(file) < 0 && errno != ENOENT && errno != ENOTDIR)
1949+ VIR_WARN("Failed to remove domain XML for %s: %s",
1950+ vm->def->name, virStrerror(errno, ebuf, sizeof(ebuf)));
1951+ VIR_FREE(file);
1952+
1953+ if (priv->pidfile &&
1954+ unlink(priv->pidfile) < 0 &&
1955+ errno != ENOENT)
1956+ VIR_WARN("Failed to remove PID file for %s: %s",
1957+ vm->def->name, virStrerror(errno, ebuf, sizeof(ebuf)));
1958+
1959+ return 0;
1960+}
1961+
1962+
1963+/* XXX figure out how to remove this */
1964+extern struct qemud_driver *qemu_driver;
1965+
1966+/*
1967+ * This is a callback registered with a qemuAgentPtr instance,
1968+ * and to be invoked when the agent console hits an end of file
1969+ * condition, or error, thus indicating VM shutdown should be
1970+ * performed
1971+ */
1972+static void
1973+qemuProcessHandleAgentEOF(qemuAgentPtr agent,
1974+ virDomainObjPtr vm)
1975+{
1976+ struct qemud_driver *driver = qemu_driver;
1977+ qemuDomainObjPrivatePtr priv;
1978+
1979+ VIR_DEBUG("Received EOF from agent on %p '%s'", vm, vm->def->name);
1980+
1981+ qemuDriverLock(driver);
1982+ virDomainObjLock(vm);
1983+
1984+ priv = vm->privateData;
1985+ if (priv->agent == agent)
1986+ priv->agent = NULL;
1987+
1988+ virDomainObjUnlock(vm);
1989+ qemuDriverUnlock(driver);
1990+
1991+ qemuAgentClose(agent);
1992+}
1993+
1994+
1995+/*
1996+ * This is invoked when there is some kind of error
1997+ * parsing data to/from the agent. The VM can continue
1998+ * to run, but no further agent commands will be
1999+ * allowed
2000+ */
2001+static void
2002+qemuProcessHandleAgentError(qemuAgentPtr agent ATTRIBUTE_UNUSED,
2003+ virDomainObjPtr vm)
2004+{
2005+ struct qemud_driver *driver = qemu_driver;
2006+ qemuDomainObjPrivatePtr priv;
2007+
2008+ VIR_DEBUG("Received error from agent on %p '%s'", vm, vm->def->name);
2009+
2010+ qemuDriverLock(driver);
2011+ virDomainObjLock(vm);
2012+
2013+ priv = vm->privateData;
2014+
2015+ priv->agentError = true;
2016+
2017+ virDomainObjUnlock(vm);
2018+ qemuDriverUnlock(driver);
2019+}
2020+
2021+static void qemuProcessHandleAgentDestroy(qemuAgentPtr agent,
2022+ virDomainObjPtr vm)
2023+{
2024+ VIR_DEBUG("Received destroy agent=%p vm=%p", agent, vm);
2025+
2026+ virObjectUnref(vm);
2027+}
2028+
2029+
2030+static qemuAgentCallbacks agentCallbacks = {
2031+ .destroy = qemuProcessHandleAgentDestroy,
2032+ .eofNotify = qemuProcessHandleAgentEOF,
2033+ .errorNotify = qemuProcessHandleAgentError,
2034+};
2035+
2036+static virDomainChrSourceDefPtr
2037+qemuFindAgentConfig(virDomainDefPtr def)
2038+{
2039+ virDomainChrSourceDefPtr config = NULL;
2040+ int i;
2041+
2042+ for (i = 0 ; i < def->nchannels ; i++) {
2043+ virDomainChrDefPtr channel = def->channels[i];
2044+
2045+ if (channel->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO)
2046+ continue;
2047+
2048+ if (STREQ_NULLABLE(channel->target.name, "org.qemu.guest_agent.0")) {
2049+ config = &channel->source;
2050+ break;
2051+ }
2052+ }
2053+
2054+ return config;
2055+}
2056+
2057+static int
2058+qemuConnectAgent(struct qemud_driver *driver, virDomainObjPtr vm)
2059+{
2060+ qemuDomainObjPrivatePtr priv = vm->privateData;
2061+ int ret = -1;
2062+ qemuAgentPtr agent = NULL;
2063+ virDomainChrSourceDefPtr config = qemuFindAgentConfig(vm->def);
2064+
2065+ if (!config)
2066+ return 0;
2067+
2068+ if (virSecurityManagerSetDaemonSocketLabel(driver->securityManager,
2069+ vm->def) < 0) {
2070+ VIR_ERROR(_("Failed to set security context for agent for %s"),
2071+ vm->def->name);
2072+ goto cleanup;
2073+ }
2074+
2075+ /* Hold an extra reference because we can't allow 'vm' to be
2076+ * deleted while the agent is active */
2077+ virObjectRef(vm);
2078+
2079+ ignore_value(virTimeMillisNow(&priv->agentStart));
2080+ virDomainObjUnlock(vm);
2081+ qemuDriverUnlock(driver);
2082+
2083+ agent = qemuAgentOpen(vm,
2084+ config,
2085+ &agentCallbacks);
2086+
2087+ qemuDriverLock(driver);
2088+ virDomainObjLock(vm);
2089+ priv->agentStart = 0;
2090+
2091+ if (virSecurityManagerClearSocketLabel(driver->securityManager,
2092+ vm->def) < 0) {
2093+ VIR_ERROR(_("Failed to clear security context for agent for %s"),
2094+ vm->def->name);
2095+ goto cleanup;
2096+ }
2097+
2098+ if (agent == NULL)
2099+ virObjectUnref(vm);
2100+
2101+ if (!virDomainObjIsActive(vm)) {
2102+ qemuAgentClose(agent);
2103+ goto cleanup;
2104+ }
2105+ priv->agent = agent;
2106+
2107+ if (priv->agent == NULL) {
2108+ VIR_INFO("Failed to connect agent for %s", vm->def->name);
2109+ goto cleanup;
2110+ }
2111+
2112+ ret = 0;
2113+
2114+cleanup:
2115+ return ret;
2116+}
2117+
2118+
2119+/*
2120+ * This is a callback registered with a qemuMonitorPtr instance,
2121+ * and to be invoked when the monitor console hits an end of file
2122+ * condition, or error, thus indicating VM shutdown should be
2123+ * performed
2124+ */
2125+static void
2126+qemuProcessHandleMonitorEOF(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
2127+ virDomainObjPtr vm)
2128+{
2129+ struct qemud_driver *driver = qemu_driver;
2130+ virDomainEventPtr event = NULL;
2131+ qemuDomainObjPrivatePtr priv;
2132+ int eventReason = VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN;
2133+ int stopReason = VIR_DOMAIN_SHUTOFF_SHUTDOWN;
2134+ const char *auditReason = "shutdown";
2135+
2136+ VIR_DEBUG("Received EOF on %p '%s'", vm, vm->def->name);
2137+
2138+ qemuDriverLock(driver);
2139+ virDomainObjLock(vm);
2140+
2141+ priv = vm->privateData;
2142+
2143+ if (priv->beingDestroyed) {
2144+ VIR_DEBUG("Domain is being destroyed, EOF is expected");
2145+ goto unlock;
2146+ }
2147+
2148+ if (!virDomainObjIsActive(vm)) {
2149+ VIR_DEBUG("Domain %p is not active, ignoring EOF", vm);
2150+ goto unlock;
2151+ }
2152+
2153+ if (priv->monJSON && !priv->gotShutdown) {
2154+ VIR_DEBUG("Monitor connection to '%s' closed without SHUTDOWN event; "
2155+ "assuming the domain crashed", vm->def->name);
2156+ eventReason = VIR_DOMAIN_EVENT_STOPPED_FAILED;
2157+ stopReason = VIR_DOMAIN_SHUTOFF_CRASHED;
2158+ auditReason = "failed";
2159+ }
2160+
2161+ event = virDomainEventNewFromObj(vm,
2162+ VIR_DOMAIN_EVENT_STOPPED,
2163+ eventReason);
2164+ qemuProcessStop(driver, vm, stopReason, 0);
2165+ virDomainAuditStop(vm, auditReason);
2166+
2167+ if (!vm->persistent) {
2168+ qemuDomainRemoveInactive(driver, vm);
2169+ goto cleanup;
2170+ }
2171+
2172+unlock:
2173+ virDomainObjUnlock(vm);
2174+
2175+cleanup:
2176+ if (event)
2177+ qemuDomainEventQueue(driver, event);
2178+ qemuDriverUnlock(driver);
2179+}
2180+
2181+
2182+/*
2183+ * This is invoked when there is some kind of error
2184+ * parsing data to/from the monitor. The VM can continue
2185+ * to run, but no further monitor commands will be
2186+ * allowed
2187+ */
2188+static void
2189+qemuProcessHandleMonitorError(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
2190+ virDomainObjPtr vm)
2191+{
2192+ struct qemud_driver *driver = qemu_driver;
2193+ virDomainEventPtr event = NULL;
2194+
2195+ VIR_DEBUG("Received error on %p '%s'", vm, vm->def->name);
2196+
2197+ qemuDriverLock(driver);
2198+ virDomainObjLock(vm);
2199+
2200+ ((qemuDomainObjPrivatePtr) vm->privateData)->monError = true;
2201+ event = virDomainEventControlErrorNewFromObj(vm);
2202+ if (event)
2203+ qemuDomainEventQueue(driver, event);
2204+
2205+ virDomainObjUnlock(vm);
2206+ qemuDriverUnlock(driver);
2207+}
2208+
2209+
2210+static virDomainDiskDefPtr
2211+qemuProcessFindDomainDiskByPath(virDomainObjPtr vm,
2212+ const char *path)
2213+{
2214+ int i = virDomainDiskIndexByName(vm->def, path, true);
2215+
2216+ if (i >= 0)
2217+ return vm->def->disks[i];
2218+
2219+ virReportError(VIR_ERR_INTERNAL_ERROR,
2220+ _("no disk found with path %s"),
2221+ path);
2222+ return NULL;
2223+}
2224+
2225+static virDomainDiskDefPtr
2226+qemuProcessFindDomainDiskByAlias(virDomainObjPtr vm,
2227+ const char *alias)
2228+{
2229+ int i;
2230+
2231+ if (STRPREFIX(alias, QEMU_DRIVE_HOST_PREFIX))
2232+ alias += strlen(QEMU_DRIVE_HOST_PREFIX);
2233+
2234+ for (i = 0; i < vm->def->ndisks; i++) {
2235+ virDomainDiskDefPtr disk;
2236+
2237+ disk = vm->def->disks[i];
2238+ if (disk->info.alias != NULL && STREQ(disk->info.alias, alias))
2239+ return disk;
2240+ }
2241+
2242+ virReportError(VIR_ERR_INTERNAL_ERROR,
2243+ _("no disk found with alias %s"),
2244+ alias);
2245+ return NULL;
2246+}
2247+
2248+static int
2249+qemuProcessGetVolumeQcowPassphrase(virConnectPtr conn,
2250+ virDomainDiskDefPtr disk,
2251+ char **secretRet,
2252+ size_t *secretLen)
2253+{
2254+ virSecretPtr secret;
2255+ char *passphrase;
2256+ unsigned char *data;
2257+ size_t size;
2258+ int ret = -1;
2259+ virStorageEncryptionPtr enc;
2260+
2261+ if (!disk->encryption) {
2262+ virReportError(VIR_ERR_INTERNAL_ERROR,
2263+ _("disk %s does not have any encryption information"),
2264+ disk->src);
2265+ return -1;
2266+ }
2267+ enc = disk->encryption;
2268+
2269+ if (!conn) {
2270+ virReportError(VIR_ERR_INTERNAL_ERROR,
2271+ "%s", _("cannot find secrets without a connection"));
2272+ goto cleanup;
2273+ }
2274+
2275+ if (conn->secretDriver == NULL ||
2276+ conn->secretDriver->lookupByUUID == NULL ||
2277+ conn->secretDriver->getValue == NULL) {
2278+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2279+ _("secret storage not supported"));
2280+ goto cleanup;
2281+ }
2282+
2283+ if (enc->format != VIR_STORAGE_ENCRYPTION_FORMAT_QCOW ||
2284+ enc->nsecrets != 1 ||
2285+ enc->secrets[0]->type !=
2286+ VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE) {
2287+ virReportError(VIR_ERR_XML_ERROR,
2288+ _("invalid <encryption> for volume %s"), disk->src);
2289+ goto cleanup;
2290+ }
2291+
2292+ secret = conn->secretDriver->lookupByUUID(conn,
2293+ enc->secrets[0]->uuid);
2294+ if (secret == NULL)
2295+ goto cleanup;
2296+ data = conn->secretDriver->getValue(secret, &size, 0,
2297+ VIR_SECRET_GET_VALUE_INTERNAL_CALL);
2298+ virObjectUnref(secret);
2299+ if (data == NULL)
2300+ goto cleanup;
2301+
2302+ if (memchr(data, '\0', size) != NULL) {
2303+ memset(data, 0, size);
2304+ VIR_FREE(data);
2305+ virReportError(VIR_ERR_XML_ERROR,
2306+ _("format='qcow' passphrase for %s must not contain a "
2307+ "'\\0'"), disk->src);
2308+ goto cleanup;
2309+ }
2310+
2311+ if (VIR_ALLOC_N(passphrase, size + 1) < 0) {
2312+ memset(data, 0, size);
2313+ VIR_FREE(data);
2314+ virReportOOMError();
2315+ goto cleanup;
2316+ }
2317+ memcpy(passphrase, data, size);
2318+ passphrase[size] = '\0';
2319+
2320+ memset(data, 0, size);
2321+ VIR_FREE(data);
2322+
2323+ *secretRet = passphrase;
2324+ *secretLen = size;
2325+
2326+ ret = 0;
2327+
2328+cleanup:
2329+ return ret;
2330+}
2331+
2332+static int
2333+qemuProcessFindVolumeQcowPassphrase(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
2334+ virConnectPtr conn,
2335+ virDomainObjPtr vm,
2336+ const char *path,
2337+ char **secretRet,
2338+ size_t *secretLen)
2339+{
2340+ virDomainDiskDefPtr disk;
2341+ int ret = -1;
2342+
2343+ virDomainObjLock(vm);
2344+ disk = qemuProcessFindDomainDiskByPath(vm, path);
2345+
2346+ if (!disk)
2347+ goto cleanup;
2348+
2349+ ret = qemuProcessGetVolumeQcowPassphrase(conn, disk, secretRet, secretLen);
2350+
2351+cleanup:
2352+ virDomainObjUnlock(vm);
2353+ return ret;
2354+}
2355+
2356+
2357+static int
2358+qemuProcessHandleReset(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
2359+ virDomainObjPtr vm)
2360+{
2361+ struct qemud_driver *driver = qemu_driver;
2362+ virDomainEventPtr event;
2363+ qemuDomainObjPrivatePtr priv;
2364+
2365+ virDomainObjLock(vm);
2366+
2367+ event = virDomainEventRebootNewFromObj(vm);
2368+ priv = vm->privateData;
2369+ if (priv->agent)
2370+ qemuAgentNotifyEvent(priv->agent, QEMU_AGENT_EVENT_RESET);
2371+
2372+ virDomainObjUnlock(vm);
2373+
2374+ if (event) {
2375+ qemuDriverLock(driver);
2376+ qemuDomainEventQueue(driver, event);
2377+ qemuDriverUnlock(driver);
2378+ }
2379+
2380+ return 0;
2381+}
2382+
2383+
2384+/*
2385+ * Since we have the '-no-shutdown' flag set, the
2386+ * QEMU process will currently have guest OS shutdown
2387+ * and the CPUS stopped. To fake the reboot, we thus
2388+ * want todo a reset of the virtual hardware, followed
2389+ * by restart of the CPUs. This should result in the
2390+ * guest OS booting up again
2391+ */
2392+static void
2393+qemuProcessFakeReboot(void *opaque)
2394+{
2395+ struct qemud_driver *driver = qemu_driver;
2396+ virDomainObjPtr vm = opaque;
2397+ qemuDomainObjPrivatePtr priv = vm->privateData;
2398+ virDomainEventPtr event = NULL;
2399+ int ret = -1;
2400+ VIR_DEBUG("vm=%p", vm);
2401+ qemuDriverLock(driver);
2402+ virDomainObjLock(vm);
2403+ if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2404+ goto cleanup;
2405+
2406+ if (!virDomainObjIsActive(vm)) {
2407+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2408+ _("guest unexpectedly quit"));
2409+ goto endjob;
2410+ }
2411+
2412+ qemuDomainObjEnterMonitorWithDriver(driver, vm);
2413+ if (qemuMonitorSystemReset(priv->mon) < 0) {
2414+ qemuDomainObjExitMonitorWithDriver(driver, vm);
2415+ goto endjob;
2416+ }
2417+ qemuDomainObjExitMonitorWithDriver(driver, vm);
2418+
2419+ if (!virDomainObjIsActive(vm)) {
2420+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2421+ _("guest unexpectedly quit"));
2422+ goto endjob;
2423+ }
2424+
2425+ if (qemuProcessStartCPUs(driver, vm, NULL,
2426+ VIR_DOMAIN_RUNNING_BOOTED,
2427+ QEMU_ASYNC_JOB_NONE) < 0) {
2428+ if (virGetLastError() == NULL)
2429+ virReportError(VIR_ERR_INTERNAL_ERROR,
2430+ "%s", _("resume operation failed"));
2431+ goto endjob;
2432+ }
2433+ priv->gotShutdown = false;
2434+ event = virDomainEventNewFromObj(vm,
2435+ VIR_DOMAIN_EVENT_RESUMED,
2436+ VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
2437+
2438+ ret = 0;
2439+
2440+endjob:
2441+ if (!qemuDomainObjEndJob(driver, vm))
2442+ vm = NULL;
2443+
2444+cleanup:
2445+ if (vm) {
2446+ if (ret == -1) {
2447+ ignore_value(qemuProcessKill(driver, vm,
2448+ VIR_QEMU_PROCESS_KILL_FORCE));
2449+ }
2450+ if (virObjectUnref(vm))
2451+ virDomainObjUnlock(vm);
2452+ }
2453+ if (event)
2454+ qemuDomainEventQueue(driver, event);
2455+ qemuDriverUnlock(driver);
2456+}
2457+
2458+
2459+static void
2460+qemuProcessShutdownOrReboot(struct qemud_driver *driver,
2461+ virDomainObjPtr vm)
2462+{
2463+ qemuDomainObjPrivatePtr priv = vm->privateData;
2464+
2465+ if (priv->fakeReboot) {
2466+ qemuDomainSetFakeReboot(driver, vm, false);
2467+ virObjectRef(vm);
2468+ virThread th;
2469+ if (virThreadCreate(&th,
2470+ false,
2471+ qemuProcessFakeReboot,
2472+ vm) < 0) {
2473+ VIR_ERROR(_("Failed to create reboot thread, killing domain"));
2474+ ignore_value(qemuProcessKill(driver, vm,
2475+ VIR_QEMU_PROCESS_KILL_NOWAIT));
2476+ virObjectUnref(vm);
2477+ }
2478+ } else {
2479+ ignore_value(qemuProcessKill(driver, vm, VIR_QEMU_PROCESS_KILL_NOWAIT));
2480+ }
2481+}
2482+
2483+static int
2484+qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
2485+ virDomainObjPtr vm)
2486+{
2487+ struct qemud_driver *driver = qemu_driver;
2488+ qemuDomainObjPrivatePtr priv;
2489+ virDomainEventPtr event = NULL;
2490+
2491+ VIR_DEBUG("vm=%p", vm);
2492+
2493+ virDomainObjLock(vm);
2494+
2495+ priv = vm->privateData;
2496+ if (priv->gotShutdown) {
2497+ VIR_DEBUG("Ignoring repeated SHUTDOWN event from domain %s",
2498+ vm->def->name);
2499+ goto unlock;
2500+ } else if (!virDomainObjIsActive(vm)) {
2501+ VIR_DEBUG("Ignoring SHUTDOWN event from inactive domain %s",
2502+ vm->def->name);
2503+ goto unlock;
2504+ }
2505+ priv->gotShutdown = true;
2506+
2507+ VIR_DEBUG("Transitioned guest %s to shutdown state",
2508+ vm->def->name);
2509+ virDomainObjSetState(vm,
2510+ VIR_DOMAIN_SHUTDOWN,
2511+ VIR_DOMAIN_SHUTDOWN_UNKNOWN);
2512+ event = virDomainEventNewFromObj(vm,
2513+ VIR_DOMAIN_EVENT_SHUTDOWN,
2514+ VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED);
2515+
2516+ if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) {
2517+ VIR_WARN("Unable to save status on vm %s after state change",
2518+ vm->def->name);
2519+ }
2520+
2521+ if (priv->agent)
2522+ qemuAgentNotifyEvent(priv->agent, QEMU_AGENT_EVENT_SHUTDOWN);
2523+
2524+ qemuProcessShutdownOrReboot(driver, vm);
2525+
2526+unlock:
2527+ virDomainObjUnlock(vm);
2528+
2529+ if (event) {
2530+ qemuDriverLock(driver);
2531+ qemuDomainEventQueue(driver, event);
2532+ qemuDriverUnlock(driver);
2533+ }
2534+
2535+ return 0;
2536+}
2537+
2538+
2539+static int
2540+qemuProcessHandleStop(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
2541+ virDomainObjPtr vm)
2542+{
2543+ struct qemud_driver *driver = qemu_driver;
2544+ virDomainEventPtr event = NULL;
2545+
2546+ virDomainObjLock(vm);
2547+ if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
2548+ qemuDomainObjPrivatePtr priv = vm->privateData;
2549+
2550+ if (priv->gotShutdown) {
2551+ VIR_DEBUG("Ignoring STOP event after SHUTDOWN");
2552+ goto unlock;
2553+ }
2554+
2555+ VIR_DEBUG("Transitioned guest %s to paused state",
2556+ vm->def->name);
2557+
2558+ virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_UNKNOWN);
2559+ event = virDomainEventNewFromObj(vm,
2560+ VIR_DOMAIN_EVENT_SUSPENDED,
2561+ VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
2562+
2563+ VIR_FREE(priv->lockState);
2564+ if (virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState) < 0)
2565+ VIR_WARN("Unable to release lease on %s", vm->def->name);
2566+ VIR_DEBUG("Preserving lock state '%s'", NULLSTR(priv->lockState));
2567+
2568+ if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) {
2569+ VIR_WARN("Unable to save status on vm %s after state change",
2570+ vm->def->name);
2571+ }
2572+ }
2573+
2574+unlock:
2575+ virDomainObjUnlock(vm);
2576+
2577+ if (event) {
2578+ qemuDriverLock(driver);
2579+ qemuDomainEventQueue(driver, event);
2580+ qemuDriverUnlock(driver);
2581+ }
2582+
2583+ return 0;
2584+}
2585+
2586+
2587+static int
2588+qemuProcessHandleRTCChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
2589+ virDomainObjPtr vm,
2590+ long long offset)
2591+{
2592+ struct qemud_driver *driver = qemu_driver;
2593+ virDomainEventPtr event;
2594+
2595+ virDomainObjLock(vm);
2596+ event = virDomainEventRTCChangeNewFromObj(vm, offset);
2597+
2598+ if (vm->def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_VARIABLE)
2599+ vm->def->clock.data.variable.adjustment = offset;
2600+
2601+ if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
2602+ VIR_WARN("unable to save domain status with RTC change");
2603+
2604+ virDomainObjUnlock(vm);
2605+
2606+ if (event) {
2607+ qemuDriverLock(driver);
2608+ qemuDomainEventQueue(driver, event);
2609+ qemuDriverUnlock(driver);
2610+ }
2611+
2612+ return 0;
2613+}
2614+
2615+
2616+static int
2617+qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
2618+ virDomainObjPtr vm,
2619+ int action)
2620+{
2621+ struct qemud_driver *driver = qemu_driver;
2622+ virDomainEventPtr watchdogEvent = NULL;
2623+ virDomainEventPtr lifecycleEvent = NULL;
2624+
2625+ virDomainObjLock(vm);
2626+ watchdogEvent = virDomainEventWatchdogNewFromObj(vm, action);
2627+
2628+ if (action == VIR_DOMAIN_EVENT_WATCHDOG_PAUSE &&
2629+ virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
2630+ qemuDomainObjPrivatePtr priv = vm->privateData;
2631+ VIR_DEBUG("Transitioned guest %s to paused state due to watchdog", vm->def->name);
2632+
2633+ virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_WATCHDOG);
2634+ lifecycleEvent = virDomainEventNewFromObj(vm,
2635+ VIR_DOMAIN_EVENT_SUSPENDED,
2636+ VIR_DOMAIN_EVENT_SUSPENDED_WATCHDOG);
2637+
2638+ VIR_FREE(priv->lockState);
2639+ if (virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState) < 0)
2640+ VIR_WARN("Unable to release lease on %s", vm->def->name);
2641+ VIR_DEBUG("Preserving lock state '%s'", NULLSTR(priv->lockState));
2642+
2643+ if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) {
2644+ VIR_WARN("Unable to save status on vm %s after watchdog event",
2645+ vm->def->name);
2646+ }
2647+ }
2648+
2649+ if (vm->def->watchdog->action == VIR_DOMAIN_WATCHDOG_ACTION_DUMP) {
2650+ struct qemuDomainWatchdogEvent *wdEvent;
2651+ if (VIR_ALLOC(wdEvent) == 0) {
2652+ wdEvent->action = VIR_DOMAIN_WATCHDOG_ACTION_DUMP;
2653+ wdEvent->vm = vm;
2654+ /* Hold an extra reference because we can't allow 'vm' to be
2655+ * deleted before handling watchdog event is finished.
2656+ */
2657+ virObjectRef(vm);
2658+ if (virThreadPoolSendJob(driver->workerPool, 0, wdEvent) < 0) {
2659+ if (!virObjectUnref(vm))
2660+ vm = NULL;
2661+ VIR_FREE(wdEvent);
2662+ }
2663+ } else {
2664+ virReportOOMError();
2665+ }
2666+ }
2667+
2668+ if (vm)
2669+ virDomainObjUnlock(vm);
2670+
2671+ if (watchdogEvent || lifecycleEvent) {
2672+ qemuDriverLock(driver);
2673+ if (watchdogEvent)
2674+ qemuDomainEventQueue(driver, watchdogEvent);
2675+ if (lifecycleEvent)
2676+ qemuDomainEventQueue(driver, lifecycleEvent);
2677+ qemuDriverUnlock(driver);
2678+ }
2679+
2680+ return 0;
2681+}
2682+
2683+
2684+static int
2685+qemuProcessHandleIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
2686+ virDomainObjPtr vm,
2687+ const char *diskAlias,
2688+ int action,
2689+ const char *reason)
2690+{
2691+ struct qemud_driver *driver = qemu_driver;
2692+ virDomainEventPtr ioErrorEvent = NULL;
2693+ virDomainEventPtr ioErrorEvent2 = NULL;
2694+ virDomainEventPtr lifecycleEvent = NULL;
2695+ const char *srcPath;
2696+ const char *devAlias;
2697+ virDomainDiskDefPtr disk;
2698+
2699+ virDomainObjLock(vm);
2700+ disk = qemuProcessFindDomainDiskByAlias(vm, diskAlias);
2701+
2702+ if (disk) {
2703+ srcPath = disk->src;
2704+ devAlias = disk->info.alias;
2705+ } else {
2706+ srcPath = "";
2707+ devAlias = "";
2708+ }
2709+
2710+ ioErrorEvent = virDomainEventIOErrorNewFromObj(vm, srcPath, devAlias, action);
2711+ ioErrorEvent2 = virDomainEventIOErrorReasonNewFromObj(vm, srcPath, devAlias, action, reason);
2712+
2713+ if (action == VIR_DOMAIN_EVENT_IO_ERROR_PAUSE &&
2714+ virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
2715+ qemuDomainObjPrivatePtr priv = vm->privateData;
2716+ VIR_DEBUG("Transitioned guest %s to paused state due to IO error", vm->def->name);
2717+
2718+ virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_IOERROR);
2719+ lifecycleEvent = virDomainEventNewFromObj(vm,
2720+ VIR_DOMAIN_EVENT_SUSPENDED,
2721+ VIR_DOMAIN_EVENT_SUSPENDED_IOERROR);
2722+
2723+ VIR_FREE(priv->lockState);
2724+ if (virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState) < 0)
2725+ VIR_WARN("Unable to release lease on %s", vm->def->name);
2726+ VIR_DEBUG("Preserving lock state '%s'", NULLSTR(priv->lockState));
2727+
2728+ if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
2729+ VIR_WARN("Unable to save status on vm %s after IO error", vm->def->name);
2730+ }
2731+ virDomainObjUnlock(vm);
2732+
2733+ if (ioErrorEvent || ioErrorEvent2 || lifecycleEvent) {
2734+ qemuDriverLock(driver);
2735+ if (ioErrorEvent)
2736+ qemuDomainEventQueue(driver, ioErrorEvent);
2737+ if (ioErrorEvent2)
2738+ qemuDomainEventQueue(driver, ioErrorEvent2);
2739+ if (lifecycleEvent)
2740+ qemuDomainEventQueue(driver, lifecycleEvent);
2741+ qemuDriverUnlock(driver);
2742+ }
2743+
2744+ return 0;
2745+}
2746+
2747+static int
2748+qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
2749+ virDomainObjPtr vm,
2750+ const char *diskAlias,
2751+ int type,
2752+ int status)
2753+{
2754+ struct qemud_driver *driver = qemu_driver;
2755+ virDomainEventPtr event = NULL;
2756+ const char *path;
2757+ virDomainDiskDefPtr disk;
2758+
2759+ virDomainObjLock(vm);
2760+ disk = qemuProcessFindDomainDiskByAlias(vm, diskAlias);
2761+
2762+ if (disk) {
2763+ path = disk->src;
2764+ event = virDomainEventBlockJobNewFromObj(vm, path, type, status);
2765+ /* XXX If we completed a block pull or commit, then recompute
2766+ * the cached backing chain to match. Better would be storing
2767+ * the chain ourselves rather than reprobing, but this
2768+ * requires modifying domain_conf and our XML to fully track
2769+ * the chain across libvirtd restarts. For that matter, if
2770+ * qemu gains support for committing the active layer, we have
2771+ * to update disk->src. */
2772+ if ((type == VIR_DOMAIN_BLOCK_JOB_TYPE_PULL ||
2773+ type == VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT) &&
2774+ status == VIR_DOMAIN_BLOCK_JOB_COMPLETED)
2775+ qemuDomainDetermineDiskChain(driver, disk, true);
2776+ if (disk->mirror && type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY &&
2777+ status == VIR_DOMAIN_BLOCK_JOB_READY)
2778+ disk->mirroring = true;
2779+ }
2780+
2781+ virDomainObjUnlock(vm);
2782+
2783+ if (event) {
2784+ qemuDriverLock(driver);
2785+ qemuDomainEventQueue(driver, event);
2786+ qemuDriverUnlock(driver);
2787+ }
2788+
2789+ return 0;
2790+}
2791+
2792+static int
2793+qemuProcessHandleGraphics(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
2794+ virDomainObjPtr vm,
2795+ int phase,
2796+ int localFamily,
2797+ const char *localNode,
2798+ const char *localService,
2799+ int remoteFamily,
2800+ const char *remoteNode,
2801+ const char *remoteService,
2802+ const char *authScheme,
2803+ const char *x509dname,
2804+ const char *saslUsername)
2805+{
2806+ struct qemud_driver *driver = qemu_driver;
2807+ virDomainEventPtr event;
2808+ virDomainEventGraphicsAddressPtr localAddr = NULL;
2809+ virDomainEventGraphicsAddressPtr remoteAddr = NULL;
2810+ virDomainEventGraphicsSubjectPtr subject = NULL;
2811+ int i;
2812+
2813+ if (VIR_ALLOC(localAddr) < 0)
2814+ goto no_memory;
2815+ localAddr->family = localFamily;
2816+ if (!(localAddr->service = strdup(localService)) ||
2817+ !(localAddr->node = strdup(localNode)))
2818+ goto no_memory;
2819+
2820+ if (VIR_ALLOC(remoteAddr) < 0)
2821+ goto no_memory;
2822+ remoteAddr->family = remoteFamily;
2823+ if (!(remoteAddr->service = strdup(remoteService)) ||
2824+ !(remoteAddr->node = strdup(remoteNode)))
2825+ goto no_memory;
2826+
2827+ if (VIR_ALLOC(subject) < 0)
2828+ goto no_memory;
2829+ if (x509dname) {
2830+ if (VIR_REALLOC_N(subject->identities, subject->nidentity+1) < 0)
2831+ goto no_memory;
2832+ subject->nidentity++;
2833+ if (!(subject->identities[subject->nidentity-1].type = strdup("x509dname")) ||
2834+ !(subject->identities[subject->nidentity-1].name = strdup(x509dname)))
2835+ goto no_memory;
2836+ }
2837+ if (saslUsername) {
2838+ if (VIR_REALLOC_N(subject->identities, subject->nidentity+1) < 0)
2839+ goto no_memory;
2840+ subject->nidentity++;
2841+ if (!(subject->identities[subject->nidentity-1].type = strdup("saslUsername")) ||
2842+ !(subject->identities[subject->nidentity-1].name = strdup(saslUsername)))
2843+ goto no_memory;
2844+ }
2845+
2846+ virDomainObjLock(vm);
2847+ event = virDomainEventGraphicsNewFromObj(vm, phase, localAddr, remoteAddr, authScheme, subject);
2848+ virDomainObjUnlock(vm);
2849+
2850+ if (event) {
2851+ qemuDriverLock(driver);
2852+ qemuDomainEventQueue(driver, event);
2853+ qemuDriverUnlock(driver);
2854+ }
2855+
2856+ return 0;
2857+
2858+no_memory:
2859+ virReportOOMError();
2860+ if (localAddr) {
2861+ VIR_FREE(localAddr->service);
2862+ VIR_FREE(localAddr->node);
2863+ VIR_FREE(localAddr);
2864+ }
2865+ if (remoteAddr) {
2866+ VIR_FREE(remoteAddr->service);
2867+ VIR_FREE(remoteAddr->node);
2868+ VIR_FREE(remoteAddr);
2869+ }
2870+ if (subject) {
2871+ for (i = 0 ; i < subject->nidentity ; i++) {
2872+ VIR_FREE(subject->identities[i].type);
2873+ VIR_FREE(subject->identities[i].name);
2874+ }
2875+ VIR_FREE(subject->identities);
2876+ VIR_FREE(subject);
2877+ }
2878+
2879+ return -1;
2880+}
2881+
2882+
2883+static void qemuProcessHandleMonitorDestroy(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
2884+ virDomainObjPtr vm)
2885+{
2886+ virObjectUnref(vm);
2887+}
2888+
2889+static int
2890+qemuProcessHandleTrayChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
2891+ virDomainObjPtr vm,
2892+ const char *devAlias,
2893+ int reason)
2894+{
2895+ struct qemud_driver *driver = qemu_driver;
2896+ virDomainEventPtr event = NULL;
2897+ virDomainDiskDefPtr disk;
2898+
2899+ virDomainObjLock(vm);
2900+ disk = qemuProcessFindDomainDiskByAlias(vm, devAlias);
2901+
2902+ if (disk) {
2903+ event = virDomainEventTrayChangeNewFromObj(vm,
2904+ devAlias,
2905+ reason);
2906+ /* Update disk tray status */
2907+ if (reason == VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN)
2908+ disk->tray_status = VIR_DOMAIN_DISK_TRAY_OPEN;
2909+ else if (reason == VIR_DOMAIN_EVENT_TRAY_CHANGE_CLOSE)
2910+ disk->tray_status = VIR_DOMAIN_DISK_TRAY_CLOSED;
2911+
2912+ if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) {
2913+ VIR_WARN("Unable to save status on vm %s after tray moved event",
2914+ vm->def->name);
2915+ }
2916+ }
2917+
2918+ virDomainObjUnlock(vm);
2919+
2920+ if (event) {
2921+ qemuDriverLock(driver);
2922+ qemuDomainEventQueue(driver, event);
2923+ qemuDriverUnlock(driver);
2924+ }
2925+
2926+ return 0;
2927+}
2928+
2929+static int
2930+qemuProcessHandlePMWakeup(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
2931+ virDomainObjPtr vm)
2932+{
2933+ struct qemud_driver *driver = qemu_driver;
2934+ virDomainEventPtr event = NULL;
2935+ virDomainEventPtr lifecycleEvent = NULL;
2936+
2937+ virDomainObjLock(vm);
2938+ event = virDomainEventPMWakeupNewFromObj(vm);
2939+
2940+ /* Don't set domain status back to running if it wasn't paused
2941+ * from guest side, otherwise it can just cause confusion.
2942+ */
2943+ if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PMSUSPENDED) {
2944+ VIR_DEBUG("Transitioned guest %s from pmsuspended to running "
2945+ "state due to QMP wakeup event", vm->def->name);
2946+
2947+ virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
2948+ VIR_DOMAIN_RUNNING_WAKEUP);
2949+ lifecycleEvent = virDomainEventNewFromObj(vm,
2950+ VIR_DOMAIN_EVENT_STARTED,
2951+ VIR_DOMAIN_EVENT_STARTED_WAKEUP);
2952+
2953+ if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) {
2954+ VIR_WARN("Unable to save status on vm %s after wakeup event",
2955+ vm->def->name);
2956+ }
2957+ }
2958+
2959+ virDomainObjUnlock(vm);
2960+
2961+ if (event || lifecycleEvent) {
2962+ qemuDriverLock(driver);
2963+ if (event)
2964+ qemuDomainEventQueue(driver, event);
2965+ if (lifecycleEvent)
2966+ qemuDomainEventQueue(driver, lifecycleEvent);
2967+ qemuDriverUnlock(driver);
2968+ }
2969+
2970+ return 0;
2971+}
2972+
2973+static int
2974+qemuProcessHandlePMSuspend(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
2975+ virDomainObjPtr vm)
2976+{
2977+ struct qemud_driver *driver = qemu_driver;
2978+ virDomainEventPtr event = NULL;
2979+ virDomainEventPtr lifecycleEvent = NULL;
2980+
2981+ virDomainObjLock(vm);
2982+ event = virDomainEventPMSuspendNewFromObj(vm);
2983+
2984+ if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
2985+ qemuDomainObjPrivatePtr priv = vm->privateData;
2986+ VIR_DEBUG("Transitioned guest %s to pmsuspended state due to "
2987+ "QMP suspend event", vm->def->name);
2988+
2989+ virDomainObjSetState(vm, VIR_DOMAIN_PMSUSPENDED,
2990+ VIR_DOMAIN_PMSUSPENDED_UNKNOWN);
2991+ lifecycleEvent =
2992+ virDomainEventNewFromObj(vm,
2993+ VIR_DOMAIN_EVENT_PMSUSPENDED,
2994+ VIR_DOMAIN_EVENT_PMSUSPENDED_MEMORY);
2995+
2996+ if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) {
2997+ VIR_WARN("Unable to save status on vm %s after suspend event",
2998+ vm->def->name);
2999+ }
3000+
3001+ if (priv->agent)
3002+ qemuAgentNotifyEvent(priv->agent, QEMU_AGENT_EVENT_SUSPEND);
3003+ }
3004+
3005+ virDomainObjUnlock(vm);
3006+
3007+ if (event || lifecycleEvent) {
3008+ qemuDriverLock(driver);
3009+ if (event)
3010+ qemuDomainEventQueue(driver, event);
3011+ if (lifecycleEvent)
3012+ qemuDomainEventQueue(driver, lifecycleEvent);
3013+ qemuDriverUnlock(driver);
3014+ }
3015+
3016+ return 0;
3017+}
3018+
3019+static int
3020+qemuProcessHandleBalloonChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
3021+ virDomainObjPtr vm,
3022+ unsigned long long actual)
3023+{
3024+ struct qemud_driver *driver = qemu_driver;
3025+ virDomainEventPtr event;
3026+
3027+ virDomainObjLock(vm);
3028+ event = virDomainEventBalloonChangeNewFromObj(vm, actual);
3029+
3030+ VIR_DEBUG("Updating balloon from %lld to %lld kb",
3031+ vm->def->mem.cur_balloon, actual);
3032+ vm->def->mem.cur_balloon = actual;
3033+
3034+ if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
3035+ VIR_WARN("unable to save domain status with balloon change");
3036+
3037+ virDomainObjUnlock(vm);
3038+
3039+ if (event) {
3040+ qemuDriverLock(driver);
3041+ qemuDomainEventQueue(driver, event);
3042+ qemuDriverUnlock(driver);
3043+ }
3044+
3045+ return 0;
3046+}
3047+
3048+static int
3049+qemuProcessHandlePMSuspendDisk(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
3050+ virDomainObjPtr vm)
3051+{
3052+ struct qemud_driver *driver = qemu_driver;
3053+ virDomainEventPtr event = NULL;
3054+ virDomainEventPtr lifecycleEvent = NULL;
3055+
3056+ virDomainObjLock(vm);
3057+ event = virDomainEventPMSuspendDiskNewFromObj(vm);
3058+
3059+ if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
3060+ qemuDomainObjPrivatePtr priv = vm->privateData;
3061+ VIR_DEBUG("Transitioned guest %s to pmsuspended state due to "
3062+ "QMP suspend_disk event", vm->def->name);
3063+
3064+ virDomainObjSetState(vm, VIR_DOMAIN_PMSUSPENDED,
3065+ VIR_DOMAIN_PMSUSPENDED_UNKNOWN);
3066+ lifecycleEvent =
3067+ virDomainEventNewFromObj(vm,
3068+ VIR_DOMAIN_EVENT_PMSUSPENDED,
3069+ VIR_DOMAIN_EVENT_PMSUSPENDED_DISK);
3070+
3071+ if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) {
3072+ VIR_WARN("Unable to save status on vm %s after suspend event",
3073+ vm->def->name);
3074+ }
3075+
3076+ if (priv->agent)
3077+ qemuAgentNotifyEvent(priv->agent, QEMU_AGENT_EVENT_SUSPEND);
3078+ }
3079+
3080+ virDomainObjUnlock(vm);
3081+
3082+ if (event || lifecycleEvent) {
3083+ qemuDriverLock(driver);
3084+ if (event)
3085+ qemuDomainEventQueue(driver, event);
3086+ if (lifecycleEvent)
3087+ qemuDomainEventQueue(driver, lifecycleEvent);
3088+ qemuDriverUnlock(driver);
3089+ }
3090+
3091+ return 0;
3092+}
3093+
3094+
3095+static qemuMonitorCallbacks monitorCallbacks = {
3096+ .destroy = qemuProcessHandleMonitorDestroy,
3097+ .eofNotify = qemuProcessHandleMonitorEOF,
3098+ .errorNotify = qemuProcessHandleMonitorError,
3099+ .diskSecretLookup = qemuProcessFindVolumeQcowPassphrase,
3100+ .domainShutdown = qemuProcessHandleShutdown,
3101+ .domainStop = qemuProcessHandleStop,
3102+ .domainReset = qemuProcessHandleReset,
3103+ .domainRTCChange = qemuProcessHandleRTCChange,
3104+ .domainWatchdog = qemuProcessHandleWatchdog,
3105+ .domainIOError = qemuProcessHandleIOError,
3106+ .domainGraphics = qemuProcessHandleGraphics,
3107+ .domainBlockJob = qemuProcessHandleBlockJob,
3108+ .domainTrayChange = qemuProcessHandleTrayChange,
3109+ .domainPMWakeup = qemuProcessHandlePMWakeup,
3110+ .domainPMSuspend = qemuProcessHandlePMSuspend,
3111+ .domainBalloonChange = qemuProcessHandleBalloonChange,
3112+ .domainPMSuspendDisk = qemuProcessHandlePMSuspendDisk,
3113+};
3114+
3115+static int
3116+qemuConnectMonitor(struct qemud_driver *driver, virDomainObjPtr vm)
3117+{
3118+ qemuDomainObjPrivatePtr priv = vm->privateData;
3119+ int ret = -1;
3120+ qemuMonitorPtr mon = NULL;
3121+
3122+ if (virSecurityManagerSetDaemonSocketLabel(driver->securityManager,
3123+ vm->def) < 0) {
3124+ VIR_ERROR(_("Failed to set security context for monitor for %s"),
3125+ vm->def->name);
3126+ goto error;
3127+ }
3128+
3129+ /* Hold an extra reference because we can't allow 'vm' to be
3130+ * deleted while the monitor is active */
3131+ virObjectRef(vm);
3132+
3133+ ignore_value(virTimeMillisNow(&priv->monStart));
3134+ virDomainObjUnlock(vm);
3135+ qemuDriverUnlock(driver);
3136+
3137+ mon = qemuMonitorOpen(vm,
3138+ priv->monConfig,
3139+ priv->monJSON,
3140+ &monitorCallbacks);
3141+
3142+ qemuDriverLock(driver);
3143+ virDomainObjLock(vm);
3144+ priv->monStart = 0;
3145+
3146+ if (mon == NULL) {
3147+ virObjectUnref(vm);
3148+ } else if (!virDomainObjIsActive(vm)) {
3149+ qemuMonitorClose(mon);
3150+ mon = NULL;
3151+ }
3152+ priv->mon = mon;
3153+
3154+ if (virSecurityManagerClearSocketLabel(driver->securityManager, vm->def) < 0) {
3155+ VIR_ERROR(_("Failed to clear security context for monitor for %s"),
3156+ vm->def->name);
3157+ goto error;
3158+ }
3159+
3160+ if (priv->mon == NULL) {
3161+ VIR_INFO("Failed to connect monitor for %s", vm->def->name);
3162+ goto error;
3163+ }
3164+
3165+
3166+ qemuDomainObjEnterMonitorWithDriver(driver, vm);
3167+ ret = qemuMonitorSetCapabilities(priv->mon);
3168+ if (ret == 0 &&
3169+ qemuCapsGet(priv->caps, QEMU_CAPS_MONITOR_JSON))
3170+ ret = qemuCapsProbeQMP(priv->caps, priv->mon);
3171+ qemuDomainObjExitMonitorWithDriver(driver, vm);
3172+
3173+error:
3174+
3175+ return ret;
3176+}
3177+
3178+typedef int qemuProcessLogHandleOutput(virDomainObjPtr vm,
3179+ const char *output,
3180+ int fd);
3181+
3182+/*
3183+ * Returns -1 for error, 0 on success
3184+ */
3185+static int
3186+qemuProcessReadLogOutput(virDomainObjPtr vm,
3187+ int fd,
3188+ char *buf,
3189+ size_t buflen,
3190+ qemuProcessLogHandleOutput func,
3191+ const char *what,
3192+ int timeout)
3193+{
3194+ int retries = (timeout*10);
3195+ int got = 0;
3196+ char *debug = NULL;
3197+ int ret = -1;
3198+ char *filter_next = buf;
3199+
3200+ buf[0] = '\0';
3201+
3202+ /* This relies on log message format generated by virLogFormatString() and
3203+ * might need to be modified when message format changes. */
3204+ if (virAsprintf(&debug, ": %d: debug : ", vm->pid) < 0) {
3205+ virReportOOMError();
3206+ return -1;
3207+ }
3208+
3209+ while (retries) {
3210+ ssize_t func_ret, bytes;
3211+ int isdead = 0;
3212+ char *eol;
3213+
3214+ func_ret = func(vm, buf, fd);
3215+
3216+ if (kill(vm->pid, 0) == -1 && errno == ESRCH)
3217+ isdead = 1;
3218+
3219+ /* Any failures should be detected before we read the log, so we
3220+ * always have something useful to report on failure. */
3221+ bytes = saferead(fd, buf+got, buflen-got-1);
3222+ if (bytes < 0) {
3223+ virReportSystemError(errno,
3224+ _("Failure while reading %s log output"),
3225+ what);
3226+ goto cleanup;
3227+ }
3228+
3229+ got += bytes;
3230+ buf[got] = '\0';
3231+
3232+ /* Filter out debug messages from intermediate libvirt process */
3233+ while ((eol = strchr(filter_next, '\n'))) {
3234+ *eol = '\0';
3235+ if (strstr(filter_next, debug)) {
3236+ memmove(filter_next, eol + 1, got - (eol - buf));
3237+ got -= eol + 1 - filter_next;
3238+ } else {
3239+ filter_next = eol + 1;
3240+ *eol = '\n';
3241+ }
3242+ }
3243+
3244+ if (got == buflen-1) {
3245+ virReportError(VIR_ERR_INTERNAL_ERROR,
3246+ _("Out of space while reading %s log output: %s"),
3247+ what, buf);
3248+ goto cleanup;
3249+ }
3250+
3251+ if (isdead) {
3252+ virReportError(VIR_ERR_INTERNAL_ERROR,
3253+ _("Process exited while reading %s log output: %s"),
3254+ what, buf);
3255+ goto cleanup;
3256+ }
3257+
3258+ if (func_ret <= 0) {
3259+ ret = func_ret;
3260+ goto cleanup;
3261+ }
3262+
3263+ usleep(100*1000);
3264+ retries--;
3265+ }
3266+
3267+ virReportError(VIR_ERR_INTERNAL_ERROR,
3268+ _("Timed out while reading %s log output: %s"),
3269+ what, buf);
3270+
3271+cleanup:
3272+ VIR_FREE(debug);
3273+ return ret;
3274+}
3275+
3276+
3277+/*
3278+ * Look at a chunk of data from the QEMU stdout logs and try to
3279+ * find a TTY device, as indicated by a line like
3280+ *
3281+ * char device redirected to /dev/pts/3
3282+ *
3283+ * Returns -1 for error, 0 success, 1 continue reading
3284+ */
3285+static int
3286+qemuProcessExtractTTYPath(const char *haystack,
3287+ size_t *offset,
3288+ char **path)
3289+{
3290+ static const char needle[] = "char device redirected to";
3291+ char *tmp, *dev;
3292+
3293+ VIR_FREE(*path);
3294+ /* First look for our magic string */
3295+ if (!(tmp = strstr(haystack + *offset, needle))) {
3296+ return 1;
3297+ }
3298+ tmp += sizeof(needle);
3299+ dev = tmp;
3300+
3301+ /*
3302+ * And look for first whitespace character and nul terminate
3303+ * to mark end of the pty path
3304+ */
3305+ while (*tmp) {
3306+ if (c_isspace(*tmp)) {
3307+ *path = strndup(dev, tmp-dev);
3308+ if (*path == NULL) {
3309+ virReportOOMError();
3310+ return -1;
3311+ }
3312+
3313+ /* ... now further update offset till we get EOL */
3314+ *offset = tmp - haystack;
3315+ return 0;
3316+ }
3317+ tmp++;
3318+ }
3319+
3320+ /*
3321+ * We found a path, but didn't find any whitespace,
3322+ * so it must be still incomplete - we should at
3323+ * least see a \n - indicate that we want to carry
3324+ * on trying again
3325+ */
3326+ return 1;
3327+}
3328+
3329+static int
3330+qemuProcessLookupPTYs(virDomainChrDefPtr *devices,
3331+ int count,
3332+ virHashTablePtr paths,
3333+ bool chardevfmt)
3334+{
3335+ int i;
3336+ const char *prefix = chardevfmt ? "char" : "";
3337+
3338+ for (i = 0 ; i < count ; i++) {
3339+ virDomainChrDefPtr chr = devices[i];
3340+ if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY) {
3341+ char id[32];
3342+ const char *path;
3343+
3344+ if (snprintf(id, sizeof(id), "%s%s",
3345+ prefix, chr->info.alias) >= sizeof(id))
3346+ return -1;
3347+
3348+ path = (const char *) virHashLookup(paths, id);
3349+ if (path == NULL) {
3350+ if (chr->source.data.file.path == NULL) {
3351+ /* neither the log output nor 'info chardev' had a
3352+ * pty path for this chardev, report an error
3353+ */
3354+ virReportError(VIR_ERR_INTERNAL_ERROR,
3355+ _("no assigned pty for device %s"), id);
3356+ return -1;
3357+ } else {
3358+ /* 'info chardev' had no pty path for this chardev,
3359+ * but the log output had, so we're fine
3360+ */
3361+ continue;
3362+ }
3363+ }
3364+
3365+ VIR_FREE(chr->source.data.file.path);
3366+ chr->source.data.file.path = strdup(path);
3367+
3368+ if (chr->source.data.file.path == NULL) {
3369+ virReportOOMError();
3370+ return -1;
3371+ }
3372+ }
3373+ }
3374+
3375+ return 0;
3376+}
3377+
3378+static int
3379+qemuProcessFindCharDevicePTYsMonitor(virDomainObjPtr vm,
3380+ qemuCapsPtr caps,
3381+ virHashTablePtr paths)
3382+{
3383+ bool chardevfmt = qemuCapsGet(caps, QEMU_CAPS_CHARDEV);
3384+
3385+ if (qemuProcessLookupPTYs(vm->def->serials, vm->def->nserials,
3386+ paths, chardevfmt) < 0)
3387+ return -1;
3388+
3389+ if (qemuProcessLookupPTYs(vm->def->parallels, vm->def->nparallels,
3390+ paths, chardevfmt) < 0)
3391+ return -1;
3392+
3393+ if (qemuProcessLookupPTYs(vm->def->channels, vm->def->nchannels,
3394+ paths, chardevfmt) < 0)
3395+ return -1;
3396+
3397+ if (qemuProcessLookupPTYs(vm->def->consoles, vm->def->nconsoles,
3398+ paths, chardevfmt) < 0)
3399+ return -1;
3400+
3401+ return 0;
3402+}
3403+
3404+static int
3405+qemuProcessFindCharDevicePTYs(virDomainObjPtr vm,
3406+ const char *output,
3407+ int fd ATTRIBUTE_UNUSED)
3408+{
3409+ size_t offset = 0;
3410+ int ret, i;
3411+
3412+ /* The order in which QEMU prints out the PTY paths is
3413+ the order in which it procsses its serial and parallel
3414+ device args. This code must match that ordering.... */
3415+
3416+ /* first comes the serial devices */
3417+ for (i = 0 ; i < vm->def->nserials ; i++) {
3418+ virDomainChrDefPtr chr = vm->def->serials[i];
3419+ if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY) {
3420+ if ((ret = qemuProcessExtractTTYPath(output, &offset,
3421+ &chr->source.data.file.path)) != 0)
3422+ return ret;
3423+ }
3424+ }
3425+
3426+ /* then the parallel devices */
3427+ for (i = 0 ; i < vm->def->nparallels ; i++) {
3428+ virDomainChrDefPtr chr = vm->def->parallels[i];
3429+ if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY) {
3430+ if ((ret = qemuProcessExtractTTYPath(output, &offset,
3431+ &chr->source.data.file.path)) != 0)
3432+ return ret;
3433+ }
3434+ }
3435+
3436+ /* then the channel devices */
3437+ for (i = 0 ; i < vm->def->nchannels ; i++) {
3438+ virDomainChrDefPtr chr = vm->def->channels[i];
3439+ if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY) {
3440+ if ((ret = qemuProcessExtractTTYPath(output, &offset,
3441+ &chr->source.data.file.path)) != 0)
3442+ return ret;
3443+ }
3444+ }
3445+
3446+ for (i = 0 ; i < vm->def->nconsoles ; i++) {
3447+ virDomainChrDefPtr chr = vm->def->consoles[i];
3448+ /* For historical reasons, console[0] can be just an alias
3449+ * for serial[0]; That's why we need to update it as well */
3450+ if (i == 0 && vm->def->nserials &&
3451+ chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
3452+ chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) {
3453+ if ((ret = virDomainChrSourceDefCopy(&chr->source,
3454+ &((vm->def->serials[0])->source))) != 0)
3455+ return ret;
3456+ } else {
3457+ if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY &&
3458+ chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO) {
3459+ if ((ret = qemuProcessExtractTTYPath(output, &offset,
3460+ &chr->source.data.file.path)) != 0)
3461+ return ret;
3462+ }
3463+ }
3464+ }
3465+
3466+ return 0;
3467+}
3468+
3469+static void qemuProcessFreePtyPath(void *payload, const void *name ATTRIBUTE_UNUSED)
3470+{
3471+ VIR_FREE(payload);
3472+}
3473+
3474+static void
3475+qemuProcessReadLogFD(int logfd, char *buf, int maxlen, int off)
3476+{
3477+ int ret;
3478+ char *tmpbuf = buf + off;
3479+
3480+ ret = saferead(logfd, tmpbuf, maxlen - off - 1);
3481+ if (ret < 0) {
3482+ ret = 0;
3483+ }
3484+
3485+ tmpbuf[ret] = '\0';
3486+}
3487+
3488+
3489+static int
3490+qemuProcessWaitForMonitor(struct qemud_driver* driver,
3491+ virDomainObjPtr vm,
3492+ qemuCapsPtr caps,
3493+ off_t pos)
3494+{
3495+ char *buf = NULL;
3496+ size_t buf_size = 4096; /* Plenty of space to get startup greeting */
3497+ int logfd = -1;
3498+ int ret = -1;
3499+ virHashTablePtr paths = NULL;
3500+ qemuDomainObjPrivatePtr priv;
3501+
3502+ if (pos != -1) {
3503+ if ((logfd = qemuDomainOpenLog(driver, vm, pos)) < 0)
3504+ return -1;
3505+
3506+ if (VIR_ALLOC_N(buf, buf_size) < 0) {
3507+ virReportOOMError();
3508+ goto closelog;
3509+ }
3510+
3511+ if (qemuProcessReadLogOutput(vm, logfd, buf, buf_size,
3512+ qemuProcessFindCharDevicePTYs,
3513+ "console", 30) < 0)
3514+ goto closelog;
3515+ }
3516+
3517+ VIR_DEBUG("Connect monitor to %p '%s'", vm, vm->def->name);
3518+ if (qemuConnectMonitor(driver, vm) < 0) {
3519+ goto cleanup;
3520+ }
3521+
3522+ /* Try to get the pty path mappings again via the monitor. This is much more
3523+ * reliable if it's available.
3524+ * Note that the monitor itself can be on a pty, so we still need to try the
3525+ * log output method. */
3526+ paths = virHashCreate(0, qemuProcessFreePtyPath);
3527+ if (paths == NULL)
3528+ goto cleanup;
3529+
3530+ priv = vm->privateData;
3531+ qemuDomainObjEnterMonitorWithDriver(driver, vm);
3532+ ret = qemuMonitorGetPtyPaths(priv->mon, paths);
3533+ qemuDomainObjExitMonitorWithDriver(driver, vm);
3534+
3535+ VIR_DEBUG("qemuMonitorGetPtyPaths returned %i", ret);
3536+ if (ret == 0)
3537+ ret = qemuProcessFindCharDevicePTYsMonitor(vm, caps, paths);
3538+
3539+cleanup:
3540+ virHashFree(paths);
3541+
3542+ if (pos != -1 && kill(vm->pid, 0) == -1 && errno == ESRCH) {
3543+ /* VM is dead, any other error raised in the interim is probably
3544+ * not as important as the qemu cmdline output */
3545+ qemuProcessReadLogFD(logfd, buf, buf_size, strlen(buf));
3546+ virReportError(VIR_ERR_INTERNAL_ERROR,
3547+ _("process exited while connecting to monitor: %s"),
3548+ buf);
3549+ ret = -1;
3550+ }
3551+
3552+closelog:
3553+ if (VIR_CLOSE(logfd) < 0) {
3554+ char ebuf[1024];
3555+ VIR_WARN("Unable to close logfile: %s",
3556+ virStrerror(errno, ebuf, sizeof(ebuf)));
3557+ }
3558+
3559+ VIR_FREE(buf);
3560+
3561+ return ret;
3562+}
3563+
3564+static int
3565+qemuProcessDetectVcpuPIDs(struct qemud_driver *driver,
3566+ virDomainObjPtr vm)
3567+{
3568+ pid_t *cpupids = NULL;
3569+ int ncpupids;
3570+ qemuDomainObjPrivatePtr priv = vm->privateData;
3571+
3572+ qemuDomainObjEnterMonitorWithDriver(driver, vm);
3573+ /* failure to get the VCPU<-> PID mapping or to execute the query
3574+ * command will not be treated fatal as some versions of qemu don't
3575+ * support this command */
3576+ if ((ncpupids = qemuMonitorGetCPUInfo(priv->mon, &cpupids)) <= 0) {
3577+ qemuDomainObjExitMonitorWithDriver(driver, vm);
3578+ virResetLastError();
3579+
3580+ priv->nvcpupids = 1;
3581+ if (VIR_ALLOC_N(priv->vcpupids, priv->nvcpupids) < 0) {
3582+ virReportOOMError();
3583+ return -1;
3584+ }
3585+ priv->vcpupids[0] = vm->pid;
3586+ return 0;
3587+ }
3588+ qemuDomainObjExitMonitorWithDriver(driver, vm);
3589+
3590+ if (ncpupids != vm->def->vcpus) {
3591+ virReportError(VIR_ERR_INTERNAL_ERROR,
3592+ _("got wrong number of vCPU pids from QEMU monitor. "
3593+ "got %d, wanted %d"),
3594+ ncpupids, vm->def->vcpus);
3595+ VIR_FREE(cpupids);
3596+ return -1;
3597+ }
3598+
3599+ priv->nvcpupids = ncpupids;
3600+ priv->vcpupids = cpupids;
3601+ return 0;
3602+}
3603+
3604+
3605+/*
3606+ * Set NUMA memory policy for qemu process, to be run between
3607+ * fork/exec of QEMU only.
3608+ */
3609+#if HAVE_NUMACTL
3610+static int
3611+qemuProcessInitNumaMemoryPolicy(virDomainObjPtr vm,
3612+ virBitmapPtr nodemask)
3613+{
3614+ nodemask_t mask;
3615+ int mode = -1;
3616+ int node = -1;
3617+ int ret = -1;
3618+ int i = 0;
3619+ int maxnode = 0;
3620+ bool warned = false;
3621+ virDomainNumatuneDef numatune = vm->def->numatune;
3622+ virBitmapPtr tmp_nodemask = NULL;
3623+
3624+ if (numatune.memory.placement_mode ==
3625+ VIR_DOMAIN_NUMATUNE_MEM_PLACEMENT_MODE_STATIC) {
3626+ if (!numatune.memory.nodemask)
3627+ return 0;
3628+ VIR_DEBUG("Set NUMA memory policy with specified nodeset");
3629+ tmp_nodemask = numatune.memory.nodemask;
3630+ } else if (numatune.memory.placement_mode ==
3631+ VIR_DOMAIN_NUMATUNE_MEM_PLACEMENT_MODE_AUTO) {
3632+ VIR_DEBUG("Set NUMA memory policy with advisory nodeset from numad");
3633+ tmp_nodemask = nodemask;
3634+ } else {
3635+ return 0;
3636+ }
3637+
3638+ if (numa_available() < 0) {
3639+ virReportError(VIR_ERR_INTERNAL_ERROR,
3640+ "%s", _("Host kernel is not aware of NUMA."));
3641+ return -1;
3642+ }
3643+
3644+ maxnode = numa_max_node() + 1;
3645+ /* Convert nodemask to NUMA bitmask. */
3646+ nodemask_zero(&mask);
3647+ i = -1;
3648+ while ((i = virBitmapNextSetBit(tmp_nodemask, i)) >= 0) {
3649+ if (i > NUMA_NUM_NODES) {
3650+ virReportError(VIR_ERR_INTERNAL_ERROR,
3651+ _("Host cannot support NUMA node %d"), i);
3652+ return -1;
3653+ }
3654+ if (i > maxnode && !warned) {
3655+ VIR_WARN("nodeset is out of range, there is only %d NUMA "
3656+ "nodes on host", maxnode);
3657+ warned = true;
3658+ }
3659+ nodemask_set(&mask, i);
3660+ }
3661+
3662+ mode = numatune.memory.mode;
3663+
3664+ if (mode == VIR_DOMAIN_NUMATUNE_MEM_STRICT) {
3665+ numa_set_bind_policy(1);
3666+ numa_set_membind(&mask);
3667+ numa_set_bind_policy(0);
3668+ } else if (mode == VIR_DOMAIN_NUMATUNE_MEM_PREFERRED) {
3669+ int nnodes = 0;
3670+ for (i = 0; i < NUMA_NUM_NODES; i++) {
3671+ if (nodemask_isset(&mask, i)) {
3672+ node = i;
3673+ nnodes++;
3674+ }
3675+ }
3676+
3677+ if (nnodes != 1) {
3678+ virReportError(VIR_ERR_INTERNAL_ERROR,
3679+ "%s", _("NUMA memory tuning in 'preferred' mode "
3680+ "only supports single node"));
3681+ goto cleanup;
3682+ }
3683+
3684+ numa_set_bind_policy(0);
3685+ numa_set_preferred(node);
3686+ } else if (mode == VIR_DOMAIN_NUMATUNE_MEM_INTERLEAVE) {
3687+ numa_set_interleave_mask(&mask);
3688+ } else {
3689+ /* XXX: Shouldn't go here, as we already do checking when
3690+ * parsing domain XML.
3691+ */
3692+ virReportError(VIR_ERR_XML_ERROR,
3693+ "%s", _("Invalid mode for memory NUMA tuning."));
3694+ goto cleanup;
3695+ }
3696+
3697+ ret = 0;
3698+
3699+cleanup:
3700+ return ret;
3701+}
3702+#else
3703+static int
3704+qemuProcessInitNumaMemoryPolicy(virDomainObjPtr vm,
3705+ virBitmapPtr nodemask ATTRIBUTE_UNUSED)
3706+{
3707+ if (vm->def->numatune.memory.nodemask) {
3708+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3709+ _("libvirt is compiled without NUMA tuning support"));
3710+
3711+ return -1;
3712+ }
3713+
3714+ return 0;
3715+}
3716+#endif
3717+
3718+#if HAVE_NUMAD
3719+static char *
3720+qemuGetNumadAdvice(virDomainDefPtr def)
3721+{
3722+ virCommandPtr cmd = NULL;
3723+ char *output = NULL;
3724+
3725+ cmd = virCommandNewArgList(NUMAD, "-w", NULL);
3726+ virCommandAddArgFormat(cmd, "%d:%llu", def->vcpus,
3727+ VIR_DIV_UP(def->mem.cur_balloon, 1024));
3728+
3729+ virCommandSetOutputBuffer(cmd, &output);
3730+
3731+ if (virCommandRun(cmd, NULL) < 0)
3732+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3733+ _("Failed to query numad for the "
3734+ "advisory nodeset"));
3735+
3736+ virCommandFree(cmd);
3737+ return output;
3738+}
3739+#else
3740+static char *
3741+qemuGetNumadAdvice(virDomainDefPtr def ATTRIBUTE_UNUSED)
3742+{
3743+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3744+ _("numad is not available on this host"));
3745+ return NULL;
3746+}
3747+#endif
3748+
3749+/* Helper to prepare cpumap for affinity setting, convert
3750+ * NUMA nodeset into cpuset if @nodemask is not NULL, otherwise
3751+ * just return a new allocated bitmap.
3752+ */
3753+virBitmapPtr
3754+qemuPrepareCpumap(struct qemud_driver *driver,
3755+ virBitmapPtr nodemask)
3756+{
3757+ int i, hostcpus, maxcpu = QEMUD_CPUMASK_LEN;
3758+ virNodeInfo nodeinfo;
3759+ virBitmapPtr cpumap = NULL;
3760+
3761+ if (nodeGetInfo(NULL, &nodeinfo) < 0)
3762+ return NULL;
3763+
3764+ /* setaffinity fails if you set bits for CPUs which
3765+ * aren't present, so we have to limit ourselves */
3766+ hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
3767+ if (maxcpu > hostcpus)
3768+ maxcpu = hostcpus;
3769+
3770+ if (!(cpumap = virBitmapNew(maxcpu))) {
3771+ virReportOOMError();
3772+ return NULL;
3773+ }
3774+
3775+ if (nodemask) {
3776+ for (i = 0; i < driver->caps->host.nnumaCell; i++) {
3777+ int j;
3778+ int cur_ncpus = driver->caps->host.numaCell[i]->ncpus;
3779+ bool result;
3780+ if (virBitmapGetBit(nodemask, i, &result) < 0) {
3781+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3782+ _("Failed to convert nodeset to cpuset"));
3783+ virBitmapFree(cpumap);
3784+ return NULL;
3785+ }
3786+ if (result) {
3787+ for (j = 0; j < cur_ncpus; j++)
3788+ ignore_value(virBitmapSetBit(cpumap,
3789+ driver->caps->host.numaCell[i]->cpus[j]));
3790+ }
3791+ }
3792+ }
3793+
3794+ return cpumap;
3795+}
3796+
3797+/*
3798+ * To be run between fork/exec of QEMU only
3799+ */
3800+static int
3801+qemuProcessInitCpuAffinity(struct qemud_driver *driver,
3802+ virDomainObjPtr vm,
3803+ virBitmapPtr nodemask)
3804+{
3805+ int ret = -1;
3806+ virBitmapPtr cpumap = NULL;
3807+ virBitmapPtr cpumapToSet = NULL;
3808+
3809+ if (!(cpumap = qemuPrepareCpumap(driver, nodemask)))
3810+ return -1;
3811+
3812+ if (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO) {
3813+ VIR_DEBUG("Set CPU affinity with advisory nodeset from numad");
3814+ cpumapToSet = cpumap;
3815+ } else {
3816+ VIR_DEBUG("Set CPU affinity with specified cpuset");
3817+ if (vm->def->cpumask) {
3818+ cpumapToSet = vm->def->cpumask;
3819+ } else {
3820+ cpumapToSet = cpumap;
3821+ /* You may think this is redundant, but we can't assume libvirtd
3822+ * itself is running on all pCPUs, so we need to explicitly set
3823+ * the spawned QEMU instance to all pCPUs if no map is given in
3824+ * its config file */
3825+ virBitmapSetAll(cpumap);
3826+ }
3827+ }
3828+
3829+ /* We are pressuming we are running between fork/exec of QEMU
3830+ * so use '0' to indicate our own process ID. No threads are
3831+ * running at this point
3832+ */
3833+ if (virProcessInfoSetAffinity(0 /* Self */, cpumapToSet) < 0)
3834+ goto cleanup;
3835+
3836+ ret = 0;
3837+
3838+cleanup:
3839+ virBitmapFree(cpumap);
3840+ return ret;
3841+}
3842+
3843+/* set link states to down on interfaces at qemu start */
3844+static int
3845+qemuProcessSetLinkStates(virDomainObjPtr vm)
3846+{
3847+ qemuDomainObjPrivatePtr priv = vm->privateData;
3848+ virDomainDefPtr def = vm->def;
3849+ int i;
3850+ int ret = 0;
3851+
3852+ for (i = 0; i < def->nnets; i++) {
3853+ if (def->nets[i]->linkstate == VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN) {
3854+ VIR_DEBUG("Setting link state: %s", def->nets[i]->info.alias);
3855+
3856+ if (!qemuCapsGet(priv->caps, QEMU_CAPS_NETDEV)) {
3857+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
3858+ _("Setting of link state is not supported by this qemu"));
3859+ return -1;
3860+ }
3861+
3862+ ret = qemuMonitorSetLink(priv->mon,
3863+ def->nets[i]->info.alias,
3864+ VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN);
3865+ if (ret != 0) {
3866+ virReportError(VIR_ERR_OPERATION_FAILED,
3867+ _("Couldn't set link state on interface: %s"), def->nets[i]->info.alias);
3868+ break;
3869+ }
3870+ }
3871+ }
3872+
3873+ return ret;
3874+}
3875+
3876+/* Set CPU affinities for vcpus if vcpupin xml provided. */
3877+static int
3878+qemuProcessSetVcpuAffinites(virConnectPtr conn ATTRIBUTE_UNUSED,
3879+ virDomainObjPtr vm)
3880+{
3881+ qemuDomainObjPrivatePtr priv = vm->privateData;
3882+ virDomainDefPtr def = vm->def;
3883+ int vcpu, n;
3884+ int ret = -1;
3885+
3886+ if (!def->cputune.nvcpupin)
3887+ return 0;
3888+
3889+ if (priv->vcpupids == NULL) {
3890+ virReportError(VIR_ERR_OPERATION_INVALID,
3891+ "%s", _("cpu affinity is not supported"));
3892+ return -1;
3893+ }
3894+
3895+ for (n = 0; n < def->cputune.nvcpupin; n++) {
3896+ vcpu = def->cputune.vcpupin[n]->vcpuid;
3897+
3898+ if (virProcessInfoSetAffinity(priv->vcpupids[vcpu],
3899+ def->cputune.vcpupin[n]->cpumask) < 0) {
3900+ goto cleanup;
3901+ }
3902+ }
3903+
3904+ ret = 0;
3905+cleanup:
3906+ return ret;
3907+}
3908+
3909+/* Set CPU affinities for emulator threads. */
3910+static int
3911+qemuProcessSetEmulatorAffinites(virConnectPtr conn ATTRIBUTE_UNUSED,
3912+ virDomainObjPtr vm)
3913+{
3914+ virBitmapPtr cpumask;
3915+ virDomainDefPtr def = vm->def;
3916+ int ret = -1;
3917+
3918+ if (def->cputune.emulatorpin)
3919+ cpumask = def->cputune.emulatorpin->cpumask;
3920+ else if (def->cpumask)
3921+ cpumask = def->cpumask;
3922+ else
3923+ return 0;
3924+
3925+ ret = virProcessInfoSetAffinity(vm->pid, cpumask);
3926+ return ret;
3927+}
3928+
3929+static int
3930+qemuProcessInitPasswords(virConnectPtr conn,
3931+ struct qemud_driver *driver,
3932+ virDomainObjPtr vm)
3933+{
3934+ int ret = 0;
3935+ qemuDomainObjPrivatePtr priv = vm->privateData;
3936+
3937+ if (vm->def->ngraphics == 1) {
3938+ if (vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
3939+ ret = qemuDomainChangeGraphicsPasswords(driver, vm,
3940+ VIR_DOMAIN_GRAPHICS_TYPE_VNC,
3941+ &vm->def->graphics[0]->data.vnc.auth,
3942+ driver->vncPassword);
3943+ } else if (vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
3944+ ret = qemuDomainChangeGraphicsPasswords(driver, vm,
3945+ VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
3946+ &vm->def->graphics[0]->data.spice.auth,
3947+ driver->spicePassword);
3948+ }
3949+ }
3950+
3951+ if (ret < 0)
3952+ goto cleanup;
3953+
3954+ if (qemuCapsGet(priv->caps, QEMU_CAPS_DEVICE)) {
3955+ int i;
3956+
3957+ for (i = 0 ; i < vm->def->ndisks ; i++) {
3958+ char *secret;
3959+ size_t secretLen;
3960+ const char *alias;
3961+
3962+ if (!vm->def->disks[i]->encryption ||
3963+ !vm->def->disks[i]->src)
3964+ continue;
3965+
3966+ if (qemuProcessGetVolumeQcowPassphrase(conn,
3967+ vm->def->disks[i],
3968+ &secret, &secretLen) < 0)
3969+ goto cleanup;
3970+
3971+ alias = vm->def->disks[i]->info.alias;
3972+ qemuDomainObjEnterMonitorWithDriver(driver, vm);
3973+ ret = qemuMonitorSetDrivePassphrase(priv->mon, alias, secret);
3974+ VIR_FREE(secret);
3975+ qemuDomainObjExitMonitorWithDriver(driver, vm);
3976+ if (ret < 0)
3977+ goto cleanup;
3978+ }
3979+ }
3980+
3981+cleanup:
3982+ return ret;
3983+}
3984+
3985+
3986+#define QEMU_PCI_VENDOR_INTEL 0x8086
3987+#define QEMU_PCI_VENDOR_LSI_LOGIC 0x1000
3988+#define QEMU_PCI_VENDOR_REDHAT 0x1af4
3989+#define QEMU_PCI_VENDOR_CIRRUS 0x1013
3990+#define QEMU_PCI_VENDOR_REALTEK 0x10ec
3991+#define QEMU_PCI_VENDOR_AMD 0x1022
3992+#define QEMU_PCI_VENDOR_ENSONIQ 0x1274
3993+#define QEMU_PCI_VENDOR_VMWARE 0x15ad
3994+#define QEMU_PCI_VENDOR_QEMU 0x1234
3995+
3996+#define QEMU_PCI_PRODUCT_DISK_VIRTIO 0x1001
3997+
3998+#define QEMU_PCI_PRODUCT_BALLOON_VIRTIO 0x1002
3999+
4000+#define QEMU_PCI_PRODUCT_NIC_NE2K 0x8029
4001+#define QEMU_PCI_PRODUCT_NIC_PCNET 0x2000
4002+#define QEMU_PCI_PRODUCT_NIC_RTL8139 0x8139
4003+#define QEMU_PCI_PRODUCT_NIC_E1000 0x100E
4004+#define QEMU_PCI_PRODUCT_NIC_VIRTIO 0x1000
4005+
4006+#define QEMU_PCI_PRODUCT_VGA_CIRRUS 0x00b8
4007+#define QEMU_PCI_PRODUCT_VGA_VMWARE 0x0405
4008+#define QEMU_PCI_PRODUCT_VGA_STDVGA 0x1111
4009+
4010+#define QEMU_PCI_PRODUCT_AUDIO_AC97 0x2415
4011+#define QEMU_PCI_PRODUCT_AUDIO_ES1370 0x5000
4012+
4013+#define QEMU_PCI_PRODUCT_CONTROLLER_PIIX 0x7010
4014+#define QEMU_PCI_PRODUCT_CONTROLLER_LSI 0x0012
4015+
4016+#define QEMU_PCI_PRODUCT_WATCHDOG_I63000ESB 0x25ab
4017+
4018+static int
4019+qemuProcessAssignNextPCIAddress(virDomainDeviceInfo *info,
4020+ int vendor,
4021+ int product,
4022+ qemuMonitorPCIAddress *addrs,
4023+ int naddrs)
4024+{
4025+ int found = 0;
4026+ int i;
4027+
4028+ VIR_DEBUG("Look for %x:%x out of %d", vendor, product, naddrs);
4029+
4030+ for (i = 0 ; (i < naddrs) && !found; i++) {
4031+ VIR_DEBUG("Maybe %x:%x", addrs[i].vendor, addrs[i].product);
4032+ if (addrs[i].vendor == vendor &&
4033+ addrs[i].product == product) {
4034+ VIR_DEBUG("Match %d", i);
4035+ found = 1;
4036+ break;
4037+ }
4038+ }
4039+ if (!found) {
4040+ return -1;
4041+ }
4042+
4043+ /* Blank it out so this device isn't matched again */
4044+ addrs[i].vendor = 0;
4045+ addrs[i].product = 0;
4046+
4047+ if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
4048+ info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
4049+
4050+ if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
4051+ info->addr.pci.domain = addrs[i].addr.domain;
4052+ info->addr.pci.bus = addrs[i].addr.bus;
4053+ info->addr.pci.slot = addrs[i].addr.slot;
4054+ info->addr.pci.function = addrs[i].addr.function;
4055+ }
4056+
4057+ return 0;
4058+}
4059+
4060+static int
4061+qemuProcessGetPCIDiskVendorProduct(virDomainDiskDefPtr def,
4062+ unsigned *vendor,
4063+ unsigned *product)
4064+{
4065+ switch (def->bus) {
4066+ case VIR_DOMAIN_DISK_BUS_VIRTIO:
4067+ *vendor = QEMU_PCI_VENDOR_REDHAT;
4068+ *product = QEMU_PCI_PRODUCT_DISK_VIRTIO;
4069+ break;
4070+
4071+ default:
4072+ return -1;
4073+ }
4074+
4075+ return 0;
4076+}
4077+
4078+static int
4079+qemuProcessGetPCINetVendorProduct(virDomainNetDefPtr def,
4080+ unsigned *vendor,
4081+ unsigned *product)
4082+{
4083+ if (!def->model)
4084+ return -1;
4085+
4086+ if (STREQ(def->model, "ne2k_pci")) {
4087+ *vendor = QEMU_PCI_VENDOR_REALTEK;
4088+ *product = QEMU_PCI_PRODUCT_NIC_NE2K;
4089+ } else if (STREQ(def->model, "pcnet")) {
4090+ *vendor = QEMU_PCI_VENDOR_AMD;
4091+ *product = QEMU_PCI_PRODUCT_NIC_PCNET;
4092+ } else if (STREQ(def->model, "rtl8139")) {
4093+ *vendor = QEMU_PCI_VENDOR_REALTEK;
4094+ *product = QEMU_PCI_PRODUCT_NIC_RTL8139;
4095+ } else if (STREQ(def->model, "e1000")) {
4096+ *vendor = QEMU_PCI_VENDOR_INTEL;
4097+ *product = QEMU_PCI_PRODUCT_NIC_E1000;
4098+ } else if (STREQ(def->model, "virtio")) {
4099+ *vendor = QEMU_PCI_VENDOR_REDHAT;
4100+ *product = QEMU_PCI_PRODUCT_NIC_VIRTIO;
4101+ } else {
4102+ VIR_INFO("Unexpected NIC model %s, cannot get PCI address",
4103+ def->model);
4104+ return -1;
4105+ }
4106+ return 0;
4107+}
4108+
4109+static int
4110+qemuProcessGetPCIControllerVendorProduct(virDomainControllerDefPtr def,
4111+ unsigned *vendor,
4112+ unsigned *product)
4113+{
4114+ switch (def->type) {
4115+ case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
4116+ *vendor = QEMU_PCI_VENDOR_LSI_LOGIC;
4117+ *product = QEMU_PCI_PRODUCT_CONTROLLER_LSI;
4118+ break;
4119+
4120+ case VIR_DOMAIN_CONTROLLER_TYPE_FDC:
4121+ /* XXX we could put in the ISA bridge address, but
4122+ that's not technically the FDC's address */
4123+ return -1;
4124+
4125+ case VIR_DOMAIN_CONTROLLER_TYPE_IDE:
4126+ *vendor = QEMU_PCI_VENDOR_INTEL;
4127+ *product = QEMU_PCI_PRODUCT_CONTROLLER_PIIX;
4128+ break;
4129+
4130+ default:
4131+ VIR_INFO("Unexpected controller type %s, cannot get PCI address",
4132+ virDomainControllerTypeToString(def->type));
4133+ return -1;
4134+ }
4135+
4136+ return 0;
4137+}
4138+
4139+static int
4140+qemuProcessGetPCIVideoVendorProduct(virDomainVideoDefPtr def,
4141+ unsigned *vendor,
4142+ unsigned *product)
4143+{
4144+ switch (def->type) {
4145+ case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
4146+ *vendor = QEMU_PCI_VENDOR_CIRRUS;
4147+ *product = QEMU_PCI_PRODUCT_VGA_CIRRUS;
4148+ break;
4149+
4150+ case VIR_DOMAIN_VIDEO_TYPE_VGA:
4151+ *vendor = QEMU_PCI_VENDOR_QEMU;
4152+ *product = QEMU_PCI_PRODUCT_VGA_STDVGA;
4153+ break;
4154+
4155+ case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
4156+ *vendor = QEMU_PCI_VENDOR_VMWARE;
4157+ *product = QEMU_PCI_PRODUCT_VGA_VMWARE;
4158+ break;
4159+
4160+ default:
4161+ return -1;
4162+ }
4163+ return 0;
4164+}
4165+
4166+static int
4167+qemuProcessGetPCISoundVendorProduct(virDomainSoundDefPtr def,
4168+ unsigned *vendor,
4169+ unsigned *product)
4170+{
4171+ switch (def->model) {
4172+ case VIR_DOMAIN_SOUND_MODEL_ES1370:
4173+ *vendor = QEMU_PCI_VENDOR_ENSONIQ;
4174+ *product = QEMU_PCI_PRODUCT_AUDIO_ES1370;
4175+ break;
4176+
4177+ case VIR_DOMAIN_SOUND_MODEL_AC97:
4178+ *vendor = QEMU_PCI_VENDOR_INTEL;
4179+ *product = QEMU_PCI_PRODUCT_AUDIO_AC97;
4180+ break;
4181+
4182+ default:
4183+ return -1;
4184+ }
4185+
4186+ return 0;
4187+}
4188+
4189+static int
4190+qemuProcessGetPCIWatchdogVendorProduct(virDomainWatchdogDefPtr def,
4191+ unsigned *vendor,
4192+ unsigned *product)
4193+{
4194+ switch (def->model) {
4195+ case VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB:
4196+ *vendor = QEMU_PCI_VENDOR_INTEL;
4197+ *product = QEMU_PCI_PRODUCT_WATCHDOG_I63000ESB;
4198+ break;
4199+
4200+ default:
4201+ return -1;
4202+ }
4203+
4204+ return 0;
4205+}
4206+
4207+
4208+static int
4209+qemuProcessGetPCIMemballoonVendorProduct(virDomainMemballoonDefPtr def,
4210+ unsigned *vendor,
4211+ unsigned *product)
4212+{
4213+ switch (def->model) {
4214+ case VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO:
4215+ *vendor = QEMU_PCI_VENDOR_REDHAT;
4216+ *product = QEMU_PCI_PRODUCT_BALLOON_VIRTIO;
4217+ break;
4218+
4219+ default:
4220+ return -1;
4221+ }
4222+
4223+ return 0;
4224+}
4225+
4226+
4227+/*
4228+ * This entire method assumes that PCI devices in 'info pci'
4229+ * match ordering of devices specified on the command line
4230+ * wrt to devices of matching vendor+product
4231+ *
4232+ * XXXX this might not be a valid assumption if we assign
4233+ * some static addrs on CLI. Have to check that...
4234+ */
4235+static int
4236+qemuProcessDetectPCIAddresses(virDomainObjPtr vm,
4237+ qemuMonitorPCIAddress *addrs,
4238+ int naddrs)
4239+{
4240+ unsigned int vendor = 0, product = 0;
4241+ int i;
4242+
4243+ /* XXX should all these vendor/product IDs be kept in the
4244+ * actual device data structure instead ?
4245+ */
4246+
4247+ for (i = 0 ; i < vm->def->ndisks ; i++) {
4248+ if (qemuProcessGetPCIDiskVendorProduct(vm->def->disks[i], &vendor, &product) < 0)
4249+ continue;
4250+
4251+ if (qemuProcessAssignNextPCIAddress(&(vm->def->disks[i]->info),
4252+ vendor, product,
4253+ addrs, naddrs) < 0) {
4254+ virReportError(VIR_ERR_INTERNAL_ERROR,
4255+ _("cannot find PCI address for VirtIO disk %s"),
4256+ vm->def->disks[i]->dst);
4257+ return -1;
4258+ }
4259+ }
4260+
4261+ for (i = 0 ; i < vm->def->nnets ; i++) {
4262+ if (qemuProcessGetPCINetVendorProduct(vm->def->nets[i], &vendor, &product) < 0)
4263+ continue;
4264+
4265+ if (qemuProcessAssignNextPCIAddress(&(vm->def->nets[i]->info),
4266+ vendor, product,
4267+ addrs, naddrs) < 0) {
4268+ virReportError(VIR_ERR_INTERNAL_ERROR,
4269+ _("cannot find PCI address for %s NIC"),
4270+ vm->def->nets[i]->model);
4271+ return -1;
4272+ }
4273+ }
4274+
4275+ for (i = 0 ; i < vm->def->ncontrollers ; i++) {
4276+ if (qemuProcessGetPCIControllerVendorProduct(vm->def->controllers[i], &vendor, &product) < 0)
4277+ continue;
4278+
4279+ if (qemuProcessAssignNextPCIAddress(&(vm->def->controllers[i]->info),
4280+ vendor, product,
4281+ addrs, naddrs) < 0) {
4282+ virReportError(VIR_ERR_INTERNAL_ERROR,
4283+ _("cannot find PCI address for controller %s"),
4284+ virDomainControllerTypeToString(vm->def->controllers[i]->type));
4285+ return -1;
4286+ }
4287+ }
4288+
4289+ for (i = 0 ; i < vm->def->nvideos ; i++) {
4290+ if (qemuProcessGetPCIVideoVendorProduct(vm->def->videos[i], &vendor, &product) < 0)
4291+ continue;
4292+
4293+ if (qemuProcessAssignNextPCIAddress(&(vm->def->videos[i]->info),
4294+ vendor, product,
4295+ addrs, naddrs) < 0) {
4296+ virReportError(VIR_ERR_INTERNAL_ERROR,
4297+ _("cannot find PCI address for video adapter %s"),
4298+ virDomainVideoTypeToString(vm->def->videos[i]->type));
4299+ return -1;
4300+ }
4301+ }
4302+
4303+ for (i = 0 ; i < vm->def->nsounds ; i++) {
4304+ if (qemuProcessGetPCISoundVendorProduct(vm->def->sounds[i], &vendor, &product) < 0)
4305+ continue;
4306+
4307+ if (qemuProcessAssignNextPCIAddress(&(vm->def->sounds[i]->info),
4308+ vendor, product,
4309+ addrs, naddrs) < 0) {
4310+ virReportError(VIR_ERR_INTERNAL_ERROR,
4311+ _("cannot find PCI address for sound adapter %s"),
4312+ virDomainSoundModelTypeToString(vm->def->sounds[i]->model));
4313+ return -1;
4314+ }
4315+ }
4316+
4317+
4318+ if (vm->def->watchdog &&
4319+ qemuProcessGetPCIWatchdogVendorProduct(vm->def->watchdog, &vendor, &product) == 0) {
4320+ if (qemuProcessAssignNextPCIAddress(&(vm->def->watchdog->info),
4321+ vendor, product,
4322+ addrs, naddrs) < 0) {
4323+ virReportError(VIR_ERR_INTERNAL_ERROR,
4324+ _("cannot find PCI address for watchdog %s"),
4325+ virDomainWatchdogModelTypeToString(vm->def->watchdog->model));
4326+ return -1;
4327+ }
4328+ }
4329+
4330+ if (vm->def->memballoon &&
4331+ qemuProcessGetPCIMemballoonVendorProduct(vm->def->memballoon, &vendor, &product) == 0) {
4332+ if (qemuProcessAssignNextPCIAddress(&(vm->def->memballoon->info),
4333+ vendor, product,
4334+ addrs, naddrs) < 0) {
4335+ virReportError(VIR_ERR_INTERNAL_ERROR,
4336+ _("cannot find PCI address for balloon %s"),
4337+ virDomainMemballoonModelTypeToString(vm->def->memballoon->model));
4338+ return -1;
4339+ }
4340+ }
4341+
4342+ /* XXX console (virtio) */
4343+
4344+
4345+ /* ... and now things we don't have in our xml */
4346+
4347+ /* XXX USB controller ? */
4348+
4349+ /* XXX what about other PCI devices (ie bridges) */
4350+
4351+ return 0;
4352+}
4353+
4354+static int
4355+qemuProcessInitPCIAddresses(struct qemud_driver *driver,
4356+ virDomainObjPtr vm)
4357+{
4358+ qemuDomainObjPrivatePtr priv = vm->privateData;
4359+ int naddrs;
4360+ int ret;
4361+ qemuMonitorPCIAddress *addrs = NULL;
4362+
4363+ qemuDomainObjEnterMonitorWithDriver(driver, vm);
4364+ naddrs = qemuMonitorGetAllPCIAddresses(priv->mon,
4365+ &addrs);
4366+ qemuDomainObjExitMonitorWithDriver(driver, vm);
4367+
4368+ ret = qemuProcessDetectPCIAddresses(vm, addrs, naddrs);
4369+
4370+ VIR_FREE(addrs);
4371+
4372+ return ret;
4373+}
4374+
4375+
4376+static int qemuProcessNextFreePort(struct qemud_driver *driver,
4377+ int startPort)
4378+{
4379+ int i;
4380+
4381+ for (i = startPort ; i < driver->remotePortMax; i++) {
4382+ int fd;
4383+ int reuse = 1;
4384+ struct sockaddr_in addr;
4385+ bool used = false;
4386+
4387+ if (virBitmapGetBit(driver->reservedRemotePorts,
4388+ i - driver->remotePortMin, &used) < 0)
4389+ VIR_DEBUG("virBitmapGetBit failed on bit %d", i - driver->remotePortMin);
4390+
4391+ if (used)
4392+ continue;
4393+
4394+ addr.sin_family = AF_INET;
4395+ addr.sin_port = htons(i);
4396+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
4397+ fd = socket(PF_INET, SOCK_STREAM, 0);
4398+ if (fd < 0)
4399+ return -1;
4400+
4401+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&reuse, sizeof(reuse)) < 0) {
4402+ VIR_FORCE_CLOSE(fd);
4403+ break;
4404+ }
4405+
4406+ if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
4407+ /* Not in use, lets grab it */
4408+ VIR_FORCE_CLOSE(fd);
4409+ /* Add port to bitmap of reserved ports */
4410+ if (virBitmapSetBit(driver->reservedRemotePorts,
4411+ i - driver->remotePortMin) < 0) {
4412+ VIR_DEBUG("virBitmapSetBit failed on bit %d",
4413+ i - driver->remotePortMin);
4414+ }
4415+ return i;
4416+ }
4417+ VIR_FORCE_CLOSE(fd);
4418+
4419+ if (errno == EADDRINUSE) {
4420+ /* In use, try next */
4421+ continue;
4422+ }
4423+ /* Some other bad failure, get out.. */
4424+ break;
4425+ }
4426+ return -1;
4427+}
4428+
4429+
4430+static void
4431+qemuProcessReturnPort(struct qemud_driver *driver,
4432+ int port)
4433+{
4434+ if (port < driver->remotePortMin)
4435+ return;
4436+
4437+ if (virBitmapClearBit(driver->reservedRemotePorts,
4438+ port - driver->remotePortMin) < 0)
4439+ VIR_DEBUG("Could not mark port %d as unused", port);
4440+}
4441+
4442+
4443+static int
4444+qemuProcessPrepareChardevDevice(virDomainDefPtr def ATTRIBUTE_UNUSED,
4445+ virDomainChrDefPtr dev,
4446+ void *opaque ATTRIBUTE_UNUSED)
4447+{
4448+ int fd;
4449+ if (dev->source.type != VIR_DOMAIN_CHR_TYPE_FILE)
4450+ return 0;
4451+
4452+ if ((fd = open(dev->source.data.file.path,
4453+ O_CREAT | O_APPEND, S_IRUSR|S_IWUSR)) < 0) {
4454+ virReportSystemError(errno,
4455+ _("Unable to pre-create chardev file '%s'"),
4456+ dev->source.data.file.path);
4457+ return -1;
4458+ }
4459+
4460+ VIR_FORCE_CLOSE(fd);
4461+
4462+ return 0;
4463+}
4464+
4465+
4466+static int
4467+qemuProcessLimits(struct qemud_driver *driver)
4468+{
4469+ struct rlimit rlim;
4470+
4471+ if (driver->maxProcesses > 0) {
4472+ rlim.rlim_cur = rlim.rlim_max = driver->maxProcesses;
4473+ if (setrlimit(RLIMIT_NPROC, &rlim) < 0) {
4474+ virReportSystemError(errno,
4475+ _("cannot limit number of processes to %d"),
4476+ driver->maxProcesses);
4477+ return -1;
4478+ }
4479+ }
4480+
4481+ if (driver->maxFiles > 0) {
4482+ /* Max number of opened files is one greater than
4483+ * actual limit. See man setrlimit */
4484+ rlim.rlim_cur = rlim.rlim_max = driver->maxFiles + 1;
4485+ if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
4486+ virReportSystemError(errno,
4487+ _("cannot set max opened files to %d"),
4488+ driver->maxFiles);
4489+ return -1;
4490+ }
4491+ }
4492+
4493+ return 0;
4494+}
4495+
4496+
4497+struct qemuProcessHookData {
4498+ virConnectPtr conn;
4499+ virDomainObjPtr vm;
4500+ struct qemud_driver *driver;
4501+ virBitmapPtr nodemask;
4502+};
4503+
4504+static int qemuProcessHook(void *data)
4505+{
4506+ struct qemuProcessHookData *h = data;
4507+ int ret = -1;
4508+ int fd;
4509+
4510+ /* Some later calls want pid present */
4511+ h->vm->pid = getpid();
4512+
4513+ VIR_DEBUG("Obtaining domain lock");
4514+ /*
4515+ * Since we're going to leak the returned FD to QEMU,
4516+ * we need to make sure it gets a sensible label.
4517+ * This mildly sucks, because there could be other
4518+ * sockets the lock driver opens that we don't want
4519+ * labelled. So far we're ok though.
4520+ */
4521+ if (virSecurityManagerSetSocketLabel(h->driver->securityManager, h->vm->def) < 0)
4522+ goto cleanup;
4523+ if (virDomainLockProcessStart(h->driver->lockManager,
4524+ h->driver->uri,
4525+ h->vm,
4526+ /* QEMU is always paused initially */
4527+ true,
4528+ &fd) < 0)
4529+ goto cleanup;
4530+ if (virSecurityManagerClearSocketLabel(h->driver->securityManager, h->vm->def) < 0)
4531+ goto cleanup;
4532+
4533+ if (qemuProcessLimits(h->driver) < 0)
4534+ goto cleanup;
4535+
4536+ /* This must take place before exec(), so that all QEMU
4537+ * memory allocation is on the correct NUMA node
4538+ */
4539+ VIR_DEBUG("Moving process to cgroup");
4540+ if (qemuAddToCgroup(h->driver, h->vm->def) < 0)
4541+ goto cleanup;
4542+
4543+ /* This must be done after cgroup placement to avoid resetting CPU
4544+ * affinity */
4545+ if (!h->vm->def->cputune.emulatorpin &&
4546+ qemuProcessInitCpuAffinity(h->driver, h->vm, h->nodemask) < 0)
4547+ goto cleanup;
4548+
4549+ if (qemuProcessInitNumaMemoryPolicy(h->vm, h->nodemask) < 0)
4550+ goto cleanup;
4551+
4552+ VIR_DEBUG("Setting up security labelling");
4553+ if (virSecurityManagerSetProcessLabel(h->driver->securityManager, h->vm->def) < 0)
4554+ goto cleanup;
4555+
4556+ ret = 0;
4557+
4558+cleanup:
4559+ VIR_DEBUG("Hook complete ret=%d", ret);
4560+ return ret;
4561+}
4562+
4563+int
4564+qemuProcessPrepareMonitorChr(struct qemud_driver *driver,
4565+ virDomainChrSourceDefPtr monConfig,
4566+ const char *vm)
4567+{
4568+ monConfig->type = VIR_DOMAIN_CHR_TYPE_UNIX;
4569+ monConfig->data.nix.listen = true;
4570+
4571+ if (virAsprintf(&monConfig->data.nix.path, "%s/%s.monitor",
4572+ driver->libDir, vm) < 0) {
4573+ virReportOOMError();
4574+ return -1;
4575+ }
4576+
4577+ return 0;
4578+}
4579+
4580+
4581+/*
4582+ * Precondition: Both driver and vm must be locked,
4583+ * and a job must be active. This method will call
4584+ * {Enter,Exit}MonitorWithDriver
4585+ */
4586+int
4587+qemuProcessStartCPUs(struct qemud_driver *driver, virDomainObjPtr vm,
4588+ virConnectPtr conn, virDomainRunningReason reason,
4589+ enum qemuDomainAsyncJob asyncJob)
4590+{
4591+ int ret;
4592+ qemuDomainObjPrivatePtr priv = vm->privateData;
4593+
4594+ VIR_DEBUG("Using lock state '%s'", NULLSTR(priv->lockState));
4595+ if (virDomainLockProcessResume(driver->lockManager, driver->uri,
4596+ vm, priv->lockState) < 0) {
4597+ /* Don't free priv->lockState on error, because we need
4598+ * to make sure we have state still present if the user
4599+ * tries to resume again
4600+ */
4601+ return -1;
4602+ }
4603+ VIR_FREE(priv->lockState);
4604+
4605+ ret = qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob);
4606+ if (ret == 0) {
4607+ ret = qemuMonitorStartCPUs(priv->mon, conn);
4608+ qemuDomainObjExitMonitorWithDriver(driver, vm);
4609+ }
4610+
4611+ if (ret == 0) {
4612+ virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
4613+ } else {
4614+ if (virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState) < 0)
4615+ VIR_WARN("Unable to release lease on %s", vm->def->name);
4616+ VIR_DEBUG("Preserving lock state '%s'", NULLSTR(priv->lockState));
4617+ }
4618+
4619+ return ret;
4620+}
4621+
4622+
4623+int qemuProcessStopCPUs(struct qemud_driver *driver, virDomainObjPtr vm,
4624+ virDomainPausedReason reason,
4625+ enum qemuDomainAsyncJob asyncJob)
4626+{
4627+ int ret;
4628+ qemuDomainObjPrivatePtr priv = vm->privateData;
4629+
4630+ VIR_FREE(priv->lockState);
4631+
4632+ ret = qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob);
4633+ if (ret == 0) {
4634+ ret = qemuMonitorStopCPUs(priv->mon);
4635+ qemuDomainObjExitMonitorWithDriver(driver, vm);
4636+ }
4637+
4638+ if (ret == 0) {
4639+ virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, reason);
4640+ if (virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState) < 0)
4641+ VIR_WARN("Unable to release lease on %s", vm->def->name);
4642+ VIR_DEBUG("Preserving lock state '%s'", NULLSTR(priv->lockState));
4643+ }
4644+
4645+ return ret;
4646+}
4647+
4648+
4649+
4650+static int
4651+qemuProcessNotifyNets(virDomainDefPtr def)
4652+{
4653+ int ii;
4654+
4655+ for (ii = 0 ; ii < def->nnets ; ii++) {
4656+ virDomainNetDefPtr net = def->nets[ii];
4657+ if (networkNotifyActualDevice(net) < 0)
4658+ return -1;
4659+ }
4660+ return 0;
4661+}
4662+
4663+static int
4664+qemuProcessFiltersInstantiate(virConnectPtr conn,
4665+ virDomainDefPtr def)
4666+{
4667+ int err = 0;
4668+ int i;
4669+
4670+ if (!conn)
4671+ return 1;
4672+
4673+ for (i = 0 ; i < def->nnets ; i++) {
4674+ virDomainNetDefPtr net = def->nets[i];
4675+ if ((net->filter) && (net->ifname)) {
4676+ if (virDomainConfNWFilterInstantiate(conn, def->uuid, net) < 0) {
4677+ err = 1;
4678+ break;
4679+ }
4680+ }
4681+ }
4682+
4683+ return err;
4684+}
4685+
4686+static int
4687+qemuProcessUpdateState(struct qemud_driver *driver, virDomainObjPtr vm)
4688+{
4689+ qemuDomainObjPrivatePtr priv = vm->privateData;
4690+ virDomainState state;
4691+ virDomainPausedReason reason;
4692+ virDomainState newState = VIR_DOMAIN_NOSTATE;
4693+ int newReason;
4694+ bool running;
4695+ char *msg = NULL;
4696+ int ret;
4697+
4698+ qemuDomainObjEnterMonitorWithDriver(driver, vm);
4699+ ret = qemuMonitorGetStatus(priv->mon, &running, &reason);
4700+ qemuDomainObjExitMonitorWithDriver(driver, vm);
4701+
4702+ if (ret < 0 || !virDomainObjIsActive(vm))
4703+ return -1;
4704+
4705+ state = virDomainObjGetState(vm, NULL);
4706+
4707+ if (state == VIR_DOMAIN_PAUSED && running) {
4708+ newState = VIR_DOMAIN_RUNNING;
4709+ newReason = VIR_DOMAIN_RUNNING_UNPAUSED;
4710+ msg = strdup("was unpaused");
4711+ } else if (state == VIR_DOMAIN_RUNNING && !running) {
4712+ if (reason == VIR_DOMAIN_PAUSED_SHUTTING_DOWN) {
4713+ newState = VIR_DOMAIN_SHUTDOWN;
4714+ newReason = VIR_DOMAIN_SHUTDOWN_UNKNOWN;
4715+ msg = strdup("shutdown");
4716+ } else {
4717+ newState = VIR_DOMAIN_PAUSED;
4718+ newReason = reason;
4719+ ignore_value(virAsprintf(&msg, "was paused (%s)",
4720+ virDomainPausedReasonTypeToString(reason)));
4721+ }
4722+ } else if (state == VIR_DOMAIN_SHUTOFF && running) {
4723+ newState = VIR_DOMAIN_RUNNING;
4724+ newReason = VIR_DOMAIN_RUNNING_BOOTED;
4725+ msg = strdup("finished booting");
4726+ }
4727+
4728+ if (newState != VIR_DOMAIN_NOSTATE) {
4729+ if (!msg) {
4730+ virReportOOMError();
4731+ return -1;
4732+ }
4733+
4734+ VIR_DEBUG("Domain %s %s while its monitor was disconnected;"
4735+ " changing state to %s (%s)",
4736+ vm->def->name,
4737+ msg,
4738+ virDomainStateTypeToString(newState),
4739+ virDomainStateReasonToString(newState, newReason));
4740+ VIR_FREE(msg);
4741+ virDomainObjSetState(vm, newState, newReason);
4742+ }
4743+
4744+ return 0;
4745+}
4746+
4747+static int
4748+qemuProcessRecoverMigration(struct qemud_driver *driver,
4749+ virDomainObjPtr vm,
4750+ virConnectPtr conn,
4751+ enum qemuDomainAsyncJob job,
4752+ enum qemuMigrationJobPhase phase,
4753+ virDomainState state,
4754+ int reason)
4755+{
4756+ qemuDomainObjPrivatePtr priv = vm->privateData;
4757+
4758+ if (job == QEMU_ASYNC_JOB_MIGRATION_IN) {
4759+ switch (phase) {
4760+ case QEMU_MIGRATION_PHASE_NONE:
4761+ case QEMU_MIGRATION_PHASE_PERFORM2:
4762+ case QEMU_MIGRATION_PHASE_BEGIN3:
4763+ case QEMU_MIGRATION_PHASE_PERFORM3:
4764+ case QEMU_MIGRATION_PHASE_PERFORM3_DONE:
4765+ case QEMU_MIGRATION_PHASE_CONFIRM3_CANCELLED:
4766+ case QEMU_MIGRATION_PHASE_CONFIRM3:
4767+ case QEMU_MIGRATION_PHASE_LAST:
4768+ break;
4769+
4770+ case QEMU_MIGRATION_PHASE_PREPARE:
4771+ VIR_DEBUG("Killing unfinished incoming migration for domain %s",
4772+ vm->def->name);
4773+ return -1;
4774+
4775+ case QEMU_MIGRATION_PHASE_FINISH2:
4776+ /* source domain is already killed so let's just resume the domain
4777+ * and hope we are all set */
4778+ VIR_DEBUG("Incoming migration finished, resuming domain %s",
4779+ vm->def->name);
4780+ if (qemuProcessStartCPUs(driver, vm, conn,
4781+ VIR_DOMAIN_RUNNING_UNPAUSED,
4782+ QEMU_ASYNC_JOB_NONE) < 0) {
4783+ VIR_WARN("Could not resume domain %s", vm->def->name);
4784+ }
4785+ break;
4786+
4787+ case QEMU_MIGRATION_PHASE_FINISH3:
4788+ /* migration finished, we started resuming the domain but didn't
4789+ * confirm success or failure yet; killing it seems safest */
4790+ VIR_DEBUG("Killing migrated domain %s", vm->def->name);
4791+ return -1;
4792+ }
4793+ } else if (job == QEMU_ASYNC_JOB_MIGRATION_OUT) {
4794+ switch (phase) {
4795+ case QEMU_MIGRATION_PHASE_NONE:
4796+ case QEMU_MIGRATION_PHASE_PREPARE:
4797+ case QEMU_MIGRATION_PHASE_FINISH2:
4798+ case QEMU_MIGRATION_PHASE_FINISH3:
4799+ case QEMU_MIGRATION_PHASE_LAST:
4800+ break;
4801+
4802+ case QEMU_MIGRATION_PHASE_BEGIN3:
4803+ /* nothing happen so far, just forget we were about to migrate the
4804+ * domain */
4805+ break;
4806+
4807+ case QEMU_MIGRATION_PHASE_PERFORM2:
4808+ case QEMU_MIGRATION_PHASE_PERFORM3:
4809+ /* migration is still in progress, let's cancel it and resume the
4810+ * domain */
4811+ VIR_DEBUG("Canceling unfinished outgoing migration of domain %s",
4812+ vm->def->name);
4813+ qemuDomainObjEnterMonitor(driver, vm);
4814+ ignore_value(qemuMonitorMigrateCancel(priv->mon));
4815+ qemuDomainObjExitMonitor(driver, vm);
4816+ /* resume the domain but only if it was paused as a result of
4817+ * migration */
4818+ if (state == VIR_DOMAIN_PAUSED &&
4819+ (reason == VIR_DOMAIN_PAUSED_MIGRATION ||
4820+ reason == VIR_DOMAIN_PAUSED_UNKNOWN)) {
4821+ if (qemuProcessStartCPUs(driver, vm, conn,
4822+ VIR_DOMAIN_RUNNING_UNPAUSED,
4823+ QEMU_ASYNC_JOB_NONE) < 0) {
4824+ VIR_WARN("Could not resume domain %s", vm->def->name);
4825+ }
4826+ }
4827+ break;
4828+
4829+ case QEMU_MIGRATION_PHASE_PERFORM3_DONE:
4830+ /* migration finished but we didn't have a chance to get the result
4831+ * of Finish3 step; third party needs to check what to do next
4832+ */
4833+ break;
4834+
4835+ case QEMU_MIGRATION_PHASE_CONFIRM3_CANCELLED:
4836+ /* Finish3 failed, we need to resume the domain */
4837+ VIR_DEBUG("Resuming domain %s after failed migration",
4838+ vm->def->name);
4839+ if (state == VIR_DOMAIN_PAUSED &&
4840+ (reason == VIR_DOMAIN_PAUSED_MIGRATION ||
4841+ reason == VIR_DOMAIN_PAUSED_UNKNOWN)) {
4842+ if (qemuProcessStartCPUs(driver, vm, conn,
4843+ VIR_DOMAIN_RUNNING_UNPAUSED,
4844+ QEMU_ASYNC_JOB_NONE) < 0) {
4845+ VIR_WARN("Could not resume domain %s", vm->def->name);
4846+ }
4847+ }
4848+ break;
4849+
4850+ case QEMU_MIGRATION_PHASE_CONFIRM3:
4851+ /* migration completed, we need to kill the domain here */
4852+ return -1;
4853+ }
4854+ }
4855+
4856+ return 0;
4857+}
4858+
4859+static int
4860+qemuProcessRecoverJob(struct qemud_driver *driver,
4861+ virDomainObjPtr vm,
4862+ virConnectPtr conn,
4863+ const struct qemuDomainJobObj *job)
4864+{
4865+ qemuDomainObjPrivatePtr priv = vm->privateData;
4866+ virDomainState state;
4867+ int reason;
4868+
4869+ state = virDomainObjGetState(vm, &reason);
4870+
4871+ switch (job->asyncJob) {
4872+ case QEMU_ASYNC_JOB_MIGRATION_OUT:
4873+ case QEMU_ASYNC_JOB_MIGRATION_IN:
4874+ if (qemuProcessRecoverMigration(driver, vm, conn, job->asyncJob,
4875+ job->phase, state, reason) < 0)
4876+ return -1;
4877+ break;
4878+
4879+ case QEMU_ASYNC_JOB_SAVE:
4880+ case QEMU_ASYNC_JOB_DUMP:
4881+ qemuDomainObjEnterMonitor(driver, vm);
4882+ ignore_value(qemuMonitorMigrateCancel(priv->mon));
4883+ qemuDomainObjExitMonitor(driver, vm);
4884+ /* resume the domain but only if it was paused as a result of
4885+ * running save/dump operation. Although we are recovering an
4886+ * async job, this function is run at startup and must resume
4887+ * things using sync monitor connections. */
4888+ if (state == VIR_DOMAIN_PAUSED &&
4889+ ((job->asyncJob == QEMU_ASYNC_JOB_DUMP &&
4890+ reason == VIR_DOMAIN_PAUSED_DUMP) ||
4891+ (job->asyncJob == QEMU_ASYNC_JOB_SAVE &&
4892+ reason == VIR_DOMAIN_PAUSED_SAVE) ||
4893+ reason == VIR_DOMAIN_PAUSED_UNKNOWN)) {
4894+ if (qemuProcessStartCPUs(driver, vm, conn,
4895+ VIR_DOMAIN_RUNNING_UNPAUSED,
4896+ QEMU_ASYNC_JOB_NONE) < 0) {
4897+ VIR_WARN("Could not resume domain %s after", vm->def->name);
4898+ }
4899+ }
4900+ break;
4901+
4902+ case QEMU_ASYNC_JOB_NONE:
4903+ case QEMU_ASYNC_JOB_LAST:
4904+ break;
4905+ }
4906+
4907+ if (!virDomainObjIsActive(vm))
4908+ return -1;
4909+
4910+ /* In case any special handling is added for job type that has been ignored
4911+ * before, QEMU_DOMAIN_TRACK_JOBS (from qemu_domain.h) needs to be updated
4912+ * for the job to be properly tracked in domain state XML.
4913+ */
4914+ switch (job->active) {
4915+ case QEMU_JOB_QUERY:
4916+ /* harmless */
4917+ break;
4918+
4919+ case QEMU_JOB_DESTROY:
4920+ VIR_DEBUG("Domain %s should have already been destroyed",
4921+ vm->def->name);
4922+ return -1;
4923+
4924+ case QEMU_JOB_SUSPEND:
4925+ /* mostly harmless */
4926+ break;
4927+
4928+ case QEMU_JOB_MODIFY:
4929+ /* XXX depending on the command we may be in an inconsistent state and
4930+ * we should probably fall back to "monitor error" state and refuse to
4931+ */
4932+ break;
4933+
4934+ case QEMU_JOB_MIGRATION_OP:
4935+ case QEMU_JOB_ABORT:
4936+ case QEMU_JOB_ASYNC:
4937+ case QEMU_JOB_ASYNC_NESTED:
4938+ /* async job was already handled above */
4939+ case QEMU_JOB_NONE:
4940+ case QEMU_JOB_LAST:
4941+ break;
4942+ }
4943+
4944+ return 0;
4945+}
4946+
4947+struct qemuProcessReconnectData {
4948+ virConnectPtr conn;
4949+ struct qemud_driver *driver;
4950+ void *payload;
4951+ struct qemuDomainJobObj oldjob;
4952+};
4953+/*
4954+ * Open an existing VM's monitor, re-detect VCPU threads
4955+ * and re-reserve the security labels in use
4956+ *
4957+ * We own the virConnectPtr we are passed here - whoever started
4958+ * this thread function has increased the reference counter to it
4959+ * so that we now have to close it.
4960+ */
4961+static void
4962+qemuProcessReconnect(void *opaque)
4963+{
4964+ struct qemuProcessReconnectData *data = opaque;
4965+ struct qemud_driver *driver = data->driver;
4966+ virDomainObjPtr obj = data->payload;
4967+ qemuDomainObjPrivatePtr priv;
4968+ virConnectPtr conn = data->conn;
4969+ struct qemuDomainJobObj oldjob;
4970+ int state;
4971+ int reason;
4972+
4973+ memcpy(&oldjob, &data->oldjob, sizeof(oldjob));
4974+
4975+ VIR_FREE(data);
4976+
4977+ qemuDriverLock(driver);
4978+ virDomainObjLock(obj);
4979+
4980+
4981+ VIR_DEBUG("Reconnect monitor to %p '%s'", obj, obj->def->name);
4982+
4983+ priv = obj->privateData;
4984+
4985+ /* Job was started by the caller for us */
4986+ qemuDomainObjTransferJob(obj);
4987+
4988+ /* Hold an extra reference because we can't allow 'vm' to be
4989+ * deleted if qemuConnectMonitor() failed */
4990+ virObjectRef(obj);
4991+
4992+ /* XXX check PID liveliness & EXE path */
4993+ if (qemuConnectMonitor(driver, obj) < 0)
4994+ goto error;
4995+
4996+ /* Failure to connect to agent shouldn't be fatal */
4997+ if (qemuConnectAgent(driver, obj) < 0) {
4998+ VIR_WARN("Cannot connect to QEMU guest agent for %s",
4999+ obj->def->name);
5000+ virResetLastError();
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: