1 /*
2  * vircgroupbackend.h: methods for cgroups backend
3  *
4  * Copyright (C) 2018 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library.  If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
21 #pragma once
22 
23 #include "internal.h"
24 
25 #include "vircgroup.h"
26 
27 #define CGROUP_MAX_VAL 512
28 
29 typedef enum {
30     VIR_CGROUP_NONE = 0, /* create subdir under each cgroup if possible. */
31     VIR_CGROUP_MEM_HIERACHY = 1 << 0, /* call virCgroupSetMemoryUseHierarchy
32                                        * before creating subcgroups and
33                                        * attaching tasks
34                                        */
35     VIR_CGROUP_THREAD = 1 << 1, /* cgroup v2 handles threads differently */
36     VIR_CGROUP_SYSTEMD = 1 << 2, /* with systemd and cgroups v2 we cannot
37                                   * manually enable controllers that systemd
38                                   * doesn't know how to delegate */
39 } virCgroupBackendFlags;
40 
41 typedef enum {
42     /* Adds a whole process with all threads to specific cgroup except
43      * to systemd named controller. */
44     VIR_CGROUP_TASK_PROCESS = 1 << 0,
45 
46     /* Same as VIR_CGROUP_TASK_PROCESS but it also adds the task to systemd
47      * named controller. */
48     VIR_CGROUP_TASK_SYSTEMD = 1 << 1,
49 
50     /* Moves only specific thread into cgroup except to systemd
51      * named controller. */
52     VIR_CGROUP_TASK_THREAD = 1 << 2,
53 } virCgroupBackendTaskFlags;
54 
55 typedef enum {
56     VIR_CGROUP_BACKEND_TYPE_V2 = 0,
57     VIR_CGROUP_BACKEND_TYPE_V1,
58     VIR_CGROUP_BACKEND_TYPE_LAST,
59 } virCgroupBackendType;
60 
61 VIR_ENUM_DECL(virCgroupBackend);
62 
63 typedef bool
64 (*virCgroupAvailableCB)(void);
65 
66 typedef bool
67 (*virCgroupValidateMachineGroupCB)(virCgroup *group,
68                                    const char *name,
69                                    const char *drivername,
70                                    const char *machinename);
71 
72 typedef int
73 (*virCgroupCopyMountsCB)(virCgroup *group,
74                          virCgroup *parent);
75 
76 typedef int
77 (*virCgroupCopyPlacementCB)(virCgroup *group,
78                             const char *path,
79                             virCgroup *parent);
80 
81 typedef int
82 (*virCgroupDetectMountsCB)(virCgroup *group,
83                            const char *mntType,
84                            const char *mntOpts,
85                            const char *mntDir);
86 
87 typedef int
88 (*virCgroupDetectPlacementCB)(virCgroup *group,
89                               const char *path,
90                               const char *controllers,
91                               const char *selfpath);
92 
93 typedef int
94 (*virCgroupSetPlacementCB)(virCgroup *group,
95                            const char *path);
96 
97 typedef int
98 (*virCgroupValidatePlacementCB)(virCgroup *group,
99                                 pid_t pid);
100 
101 typedef char *
102 (*virCgroupStealPlacementCB)(virCgroup *group);
103 
104 typedef int
105 (*virCgroupDetectControllersCB)(virCgroup *group,
106                                 int controllers,
107                                 virCgroup *parent,
108                                 int detected);
109 
110 typedef bool
111 (*virCgroupHasControllerCB)(virCgroup *cgroup,
112                             int controller);
113 
114 typedef int
115 (*virCgroupGetAnyControllerCB)(virCgroup *group);
116 
117 typedef int
118 (*virCgroupPathOfControllerCB)(virCgroup *group,
119                                int controller,
120                                const char *key,
121                                char **path);
122 
123 typedef bool
124 (*virCgroupExistsCB)(virCgroup *group);
125 
126 typedef int
127 (*virCgroupMakeGroupCB)(virCgroup *parent,
128                         virCgroup *group,
129                         bool create,
130                         pid_t pid,
131                         unsigned int flags);
132 
133 typedef int
134 (*virCgroupRemoveCB)(virCgroup *group);
135 
136 typedef int
137 (*virCgroupAddTaskCB)(virCgroup *group,
138                       pid_t pid,
139                       unsigned int flags);
140 
141 typedef int
142 (*virCgroupHasEmptyTasksCB)(virCgroup *cgroup,
143                             int controller);
144 
145 typedef int
146 (*virCgroupKillRecursiveCB)(virCgroup *group,
147                             int signum,
148                             GHashTable *pids);
149 
150 typedef int
151 (*virCgroupBindMountCB)(virCgroup *group,
152                         const char *oldroot,
153                         const char *mountopts);
154 
155 typedef int
156 (*virCgroupSetOwnerCB)(virCgroup *cgroup,
157                        uid_t uid,
158                        gid_t gid,
159                        int controllers);
160 
161 typedef int
162 (*virCgroupSetBlkioWeightCB)(virCgroup *group,
163                              unsigned int weight);
164 
165 typedef int
166 (*virCgroupGetBlkioWeightCB)(virCgroup *group,
167                              unsigned int *weight);
168 
169 typedef int
170 (*virCgroupGetBlkioIoServicedCB)(virCgroup *group,
171                                  long long *bytes_read,
172                                  long long *bytes_write,
173                                  long long *requests_read,
174                                  long long *requests_write);
175 
176 typedef int
177 (*virCgroupGetBlkioIoDeviceServicedCB)(virCgroup *group,
178                                        const char *path,
179                                        long long *bytes_read,
180                                        long long *bytes_write,
181                                        long long *requests_read,
182                                        long long *requests_write);
183 
184 typedef int
185 (*virCgroupSetBlkioDeviceWeightCB)(virCgroup *group,
186                                    const char *path,
187                                    unsigned int weight);
188 
189 typedef int
190 (*virCgroupGetBlkioDeviceWeightCB)(virCgroup *group,
191                                    const char *path,
192                                    unsigned int *weight);
193 
194 typedef int
195 (*virCgroupSetBlkioDeviceReadIopsCB)(virCgroup *group,
196                                      const char *path,
197                                      unsigned int riops);
198 
199 typedef int
200 (*virCgroupGetBlkioDeviceReadIopsCB)(virCgroup *group,
201                                      const char *path,
202                                      unsigned int *riops);
203 
204 typedef int
205 (*virCgroupSetBlkioDeviceWriteIopsCB)(virCgroup *group,
206                                       const char *path,
207                                       unsigned int wiops);
208 
209 typedef int
210 (*virCgroupGetBlkioDeviceWriteIopsCB)(virCgroup *group,
211                                       const char *path,
212                                       unsigned int *wiops);
213 
214 typedef int
215 (*virCgroupSetBlkioDeviceReadBpsCB)(virCgroup *group,
216                                     const char *path,
217                                     unsigned long long rbps);
218 
219 typedef int
220 (*virCgroupGetBlkioDeviceReadBpsCB)(virCgroup *group,
221                                     const char *path,
222                                     unsigned long long *rbps);
223 
224 typedef int
225 (*virCgroupSetBlkioDeviceWriteBpsCB)(virCgroup *group,
226                                      const char *path,
227                                      unsigned long long wbps);
228 
229 typedef int
230 (*virCgroupGetBlkioDeviceWriteBpsCB)(virCgroup *group,
231                                      const char *path,
232                                      unsigned long long *wbps);
233 
234 typedef int
235 (*virCgroupSetMemoryCB)(virCgroup *group,
236                         unsigned long long kb);
237 
238 typedef int
239 (*virCgroupGetMemoryStatCB)(virCgroup *group,
240                             unsigned long long *cache,
241                             unsigned long long *activeAnon,
242                             unsigned long long *inactiveAnon,
243                             unsigned long long *activeFile,
244                             unsigned long long *inactiveFile,
245                             unsigned long long *unevictable);
246 
247 typedef int
248 (*virCgroupGetMemoryUsageCB)(virCgroup *group,
249                              unsigned long *kb);
250 
251 typedef int
252 (*virCgroupSetMemoryHardLimitCB)(virCgroup *group,
253                                  unsigned long long kb);
254 
255 typedef int
256 (*virCgroupGetMemoryHardLimitCB)(virCgroup *group,
257                                  unsigned long long *kb);
258 
259 typedef int
260 (*virCgroupSetMemorySoftLimitCB)(virCgroup *group,
261                                  unsigned long long kb);
262 
263 typedef int
264 (*virCgroupGetMemorySoftLimitCB)(virCgroup *group,
265                                  unsigned long long *kb);
266 
267 typedef int
268 (*virCgroupSetMemSwapHardLimitCB)(virCgroup *group,
269                                   unsigned long long kb);
270 
271 typedef int
272 (*virCgroupGetMemSwapHardLimitCB)(virCgroup *group,
273                                   unsigned long long *kb);
274 
275 typedef int
276 (*virCgroupGetMemSwapUsageCB)(virCgroup *group,
277                               unsigned long long *kb);
278 
279 typedef int
280 (*virCgroupAllowDeviceCB)(virCgroup *group,
281                           char type,
282                           int major,
283                           int minor,
284                           int perms);
285 
286 typedef int
287 (*virCgroupDenyDeviceCB)(virCgroup *group,
288                          char type,
289                          int major,
290                          int minor,
291                          int perms);
292 
293 typedef int
294 (*virCgroupAllowAllDevicesCB)(virCgroup *group,
295                               int perms);
296 
297 typedef int
298 (*virCgroupDenyAllDevicesCB)(virCgroup *group);
299 
300 typedef int
301 (*virCgroupSetCpuSharesCB)(virCgroup *group,
302                            unsigned long long shares);
303 
304 typedef int
305 (*virCgroupGetCpuSharesCB)(virCgroup *group,
306                            unsigned long long *shares);
307 
308 typedef int
309 (*virCgroupSetCpuCfsPeriodCB)(virCgroup *group,
310                               unsigned long long cfs_period);
311 
312 typedef int
313 (*virCgroupGetCpuCfsPeriodCB)(virCgroup *group,
314                               unsigned long long *cfs_period);
315 
316 typedef int
317 (*virCgroupSetCpuCfsQuotaCB)(virCgroup *group,
318                              long long cfs_quota);
319 
320 typedef int
321 (*virCgroupGetCpuCfsQuotaCB)(virCgroup *group,
322                              long long *cfs_quota);
323 
324 typedef bool
325 (*virCgroupSupportsCpuBWCB)(virCgroup *cgroup);
326 
327 typedef int
328 (*virCgroupGetCpuacctUsageCB)(virCgroup *group,
329                               unsigned long long *usage);
330 
331 typedef int
332 (*virCgroupGetCpuacctPercpuUsageCB)(virCgroup *group,
333                                     char **usage);
334 
335 typedef int
336 (*virCgroupGetCpuacctStatCB)(virCgroup *group,
337                              unsigned long long *user,
338                              unsigned long long *sys);
339 
340 typedef int
341 (*virCgroupSetFreezerStateCB)(virCgroup *group,
342                               const char *state);
343 
344 typedef int
345 (*virCgroupGetFreezerStateCB)(virCgroup *group,
346                               char **state);
347 
348 typedef int
349 (*virCgroupSetCpusetMemsCB)(virCgroup *group,
350                             const char *mems);
351 
352 typedef int
353 (*virCgroupGetCpusetMemsCB)(virCgroup *group,
354                             char **mems);
355 
356 typedef int
357 (*virCgroupSetCpusetMemoryMigrateCB)(virCgroup *group,
358                                      bool migrate);
359 
360 typedef int
361 (*virCgroupGetCpusetMemoryMigrateCB)(virCgroup *group,
362                                      bool *migrate);
363 
364 typedef int
365 (*virCgroupSetCpusetCpusCB)(virCgroup *group,
366                             const char *cpus);
367 
368 typedef int
369 (*virCgroupGetCpusetCpusCB)(virCgroup *group,
370                             char **cpus);
371 
372 struct _virCgroupBackend {
373     virCgroupBackendType type;
374 
375     /* Mandatory callbacks that need to be implemented for every backend. */
376     virCgroupAvailableCB available;
377     virCgroupValidateMachineGroupCB validateMachineGroup;
378     virCgroupCopyMountsCB copyMounts;
379     virCgroupCopyPlacementCB copyPlacement;
380     virCgroupDetectMountsCB detectMounts;
381     virCgroupDetectPlacementCB detectPlacement;
382     virCgroupSetPlacementCB setPlacement;
383     virCgroupValidatePlacementCB validatePlacement;
384     virCgroupStealPlacementCB stealPlacement;
385     virCgroupDetectControllersCB detectControllers;
386     virCgroupHasControllerCB hasController;
387     virCgroupGetAnyControllerCB getAnyController;
388     virCgroupPathOfControllerCB pathOfController;
389     virCgroupMakeGroupCB makeGroup;
390     virCgroupExistsCB exists;
391     virCgroupRemoveCB remove;
392     virCgroupAddTaskCB addTask;
393     virCgroupHasEmptyTasksCB hasEmptyTasks;
394     virCgroupKillRecursiveCB killRecursive;
395     virCgroupBindMountCB bindMount;
396     virCgroupSetOwnerCB setOwner;
397 
398     /* Optional cgroup controller specific callbacks. */
399     virCgroupSetBlkioWeightCB setBlkioWeight;
400     virCgroupGetBlkioWeightCB getBlkioWeight;
401     virCgroupGetBlkioIoServicedCB getBlkioIoServiced;
402     virCgroupGetBlkioIoDeviceServicedCB getBlkioIoDeviceServiced;
403     virCgroupSetBlkioDeviceWeightCB setBlkioDeviceWeight;
404     virCgroupGetBlkioDeviceWeightCB getBlkioDeviceWeight;
405     virCgroupSetBlkioDeviceReadIopsCB setBlkioDeviceReadIops;
406     virCgroupGetBlkioDeviceReadIopsCB getBlkioDeviceReadIops;
407     virCgroupSetBlkioDeviceWriteIopsCB setBlkioDeviceWriteIops;
408     virCgroupGetBlkioDeviceWriteIopsCB getBlkioDeviceWriteIops;
409     virCgroupSetBlkioDeviceReadBpsCB setBlkioDeviceReadBps;
410     virCgroupGetBlkioDeviceReadBpsCB getBlkioDeviceReadBps;
411     virCgroupSetBlkioDeviceWriteBpsCB setBlkioDeviceWriteBps;
412     virCgroupGetBlkioDeviceWriteBpsCB getBlkioDeviceWriteBps;
413 
414     virCgroupSetMemoryCB setMemory;
415     virCgroupGetMemoryStatCB getMemoryStat;
416     virCgroupGetMemoryUsageCB getMemoryUsage;
417     virCgroupSetMemoryHardLimitCB setMemoryHardLimit;
418     virCgroupGetMemoryHardLimitCB getMemoryHardLimit;
419     virCgroupSetMemorySoftLimitCB setMemorySoftLimit;
420     virCgroupGetMemorySoftLimitCB getMemorySoftLimit;
421     virCgroupSetMemSwapHardLimitCB setMemSwapHardLimit;
422     virCgroupGetMemSwapHardLimitCB getMemSwapHardLimit;
423     virCgroupGetMemSwapUsageCB getMemSwapUsage;
424 
425     virCgroupAllowDeviceCB allowDevice;
426     virCgroupDenyDeviceCB denyDevice;
427     virCgroupAllowAllDevicesCB allowAllDevices;
428     virCgroupDenyAllDevicesCB denyAllDevices;
429 
430     virCgroupSetCpuSharesCB setCpuShares;
431     virCgroupGetCpuSharesCB getCpuShares;
432     virCgroupSetCpuCfsPeriodCB setCpuCfsPeriod;
433     virCgroupGetCpuCfsPeriodCB getCpuCfsPeriod;
434     virCgroupSetCpuCfsQuotaCB setCpuCfsQuota;
435     virCgroupGetCpuCfsQuotaCB getCpuCfsQuota;
436     virCgroupSupportsCpuBWCB supportsCpuBW;
437 
438     virCgroupGetCpuacctUsageCB getCpuacctUsage;
439     virCgroupGetCpuacctPercpuUsageCB getCpuacctPercpuUsage;
440     virCgroupGetCpuacctStatCB getCpuacctStat;
441 
442     virCgroupSetFreezerStateCB setFreezerState;
443     virCgroupGetFreezerStateCB getFreezerState;
444 
445     virCgroupSetCpusetMemsCB setCpusetMems;
446     virCgroupGetCpusetMemsCB getCpusetMems;
447     virCgroupSetCpusetMemoryMigrateCB setCpusetMemoryMigrate;
448     virCgroupGetCpusetMemoryMigrateCB getCpusetMemoryMigrate;
449     virCgroupSetCpusetCpusCB setCpusetCpus;
450     virCgroupGetCpusetCpusCB getCpusetCpus;
451 };
452 typedef struct _virCgroupBackend virCgroupBackend;
453 
454 void
455 virCgroupBackendRegister(virCgroupBackend *backend);
456 
457 virCgroupBackend **
458 virCgroupBackendGetAll(void);
459 
460 virCgroupBackend *
461 virCgroupBackendForController(virCgroup *group,
462                               unsigned int controller);
463 
464 #define VIR_CGROUP_BACKEND_CALL(group, controller, func, ret, ...) \
465     do { \
466         virCgroupBackend *backend = virCgroupBackendForController(group, controller); \
467         if (!backend) { \
468             virReportError(VIR_ERR_INTERNAL_ERROR, \
469                            _("failed to get cgroup backend for '%s' controller '%u'"), \
470                            #func, controller); \
471             return ret; \
472         } \
473         if (!backend->func) { \
474             virReportError(VIR_ERR_OPERATION_UNSUPPORTED, \
475                            _("operation '%s' not supported for backend '%s'"), \
476                            #func, virCgroupBackendTypeToString(backend->type)); \
477             return ret; \
478         } \
479         return backend->func(group, ##__VA_ARGS__); \
480     } while (0)
481